title: Is this wrapper for PDO 'good code' ? Are there any potential problems?
body: <p>I built this class to work with PDO, to make SQL queries 'easier' and less to worry about. </p>
  
  <p>Here are my thoughts</p>
  
  <ul>
  <li>Should it be more like class DB extends PDO?</li>
  <li>Is the query method too big? Should it be split into private methods which are called.. is this what is known as <em>loose coupling</em>?</li>
  <li>Is my way for detecting a SELECT query too ugly for it's own good? </li>
  <li>What other problems are evident? As I am sort of learning-as-I-go, I'm sure I could have overlooked a lot of potential problems.</li>
  </ul>
  
  <p>Thank you</p>
  
  <p>` 
  
  <pre><code> class Db
   {
      private static $_instance = NULL;
  
  
      private function __construct() {
  
          // can not call me
      }
  
      private function __clone() {
  
          // no!
      }
  
      public static function getInstance() {
  
          if (!self::$_instance)
          {
  
              try {
  
                  self::$_instance = new PDO('mysql:host=' . CONFIG_MYSQL_SERVER . ';dbname=' . CONFIG_MYSQL_DATABASE, CONFIG_MYSQL_USERNAME, CONFIG_MYSQL_PASSWORD);;
                  self::$_instance-&gt; setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
  
              } catch(PDOException $e) {
  
                  trigger_error($e-&gt;getMessage());
  
              }
  
          }
  
          return self::$_instance;
  
  
      }
  
  
  
      public static function query($query /*string*/, $bindings = NULL)
      {
  
          $queryPortion = substr($query,0, 6);
  
          try {
  
              if ($bindings) {
  
                      $prepared = self::getInstance()-&gt;prepare($query);
  
                      foreach($bindings as $binding=&gt;$data) { // defaults to string
  
                          if (!is_array($data)) {
                              $prepared-&gt;bindParam($binding, $data); 
  
                          } else {
  
                              switch(count($data)) {
  
                                  case 1:
                                      $prepared-&gt;bindParam($binding, $data['value']);
                                      break;                          
  
                                  case 2:
                                      $prepared-&gt;bindParam($binding, $data['value'], $data['dataType']);
                                      break;
  
                                  case 3:
                                      $prepared-&gt;bindParam($binding, $data['value'], $data['dataType'], (int)$data['length']);
                                      break;                          
  
                                  default:
                                      trigger_error('An error has occured with the prepared statement bindings.');
                                      return false;
                                      break;
                              }
                          }
  
                      }
  
                      $prepared-&gt;execute();
  
                      return $prepared-&gt;fetchAll(PDO::FETCH_ASSOC);
  
  
              } else if (String::match($queryPortion, 'select')) { // if this is a select query
  
                  $rows = self::getInstance()-&gt;query($query);
  
                  return $rows-&gt;fetchAll(PDO::FETCH_ASSOC);
  
              } else {
  
                  return self::getInstance()-&gt;exec($query);
  
              }
  
  
          } 
          catch(PDOException $e)
          {
              trigger_error($e-&gt;getMessage());
          }
  
  
      }
  
      public static function getLastInsertId()
      {
          try {
              self::getInstance()-&gt;lastInsertId();
            }
          catch(PDOException $e)
          {
              trigger_error($e-&gt;getMessage());
          }
  
      }
  
      public static function disconnect()
      {
          // kill PDO object
          self::$_instance = NULL;
  
      }
   }
  </code></pre>