Source for file Query.class.php

Documentation is available at Query.class.php

  1. <?php
  2. /**
  3.  * Gumbo Library Framework
  4.  *
  5.  * LICENSE
  6.  * This library is being released under the terms of the New BSD License.  A
  7.  * copy of the license is packaged with the software (LICENSE.txt).  If no
  8.  * copy is found, a copy of the license template can be found at:
  9.  * http://www.opensource.org/licenses/bsd-license.php
  10.  * 
  11.  * @category Gumbo
  12.  * @package Query
  13.  * @copyright Copyright (c) 2007, iBayou, Michael Luster
  14.  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  15.  * @author Michael Luster <mluster79@yahoo.com>
  16.  * @link http://sourceforge.net/projects/phpgumbo
  17.  * @version 0.0.1
  18.  */
  19.  
  20. /**
  21.  * Query Class
  22.  * 
  23.  * This class was designed to provide a central location for executing common
  24.  * queries (select,insert,update,delete) on a database.  The current implementation
  25.  * works with a PDO object.  Once the PDO object is created, it is assigned to
  26.  * the Query class.
  27.  * 
  28.  * "Is this abstracting the abstraction layer?"
  29.  * Probably.  This is meant to wrap specific methods inside various DB classes
  30.  * that abstract database functionality (PDO, ADODB, PEAR_DB, Zend_DB, etc.).  The
  31.  * problem was switching between them.  Each perform the same tasks, except the
  32.  * interfaces are different.  Therefore, having to switch between ADODB and PDO could
  33.  * become a large chore.  Imagine searching through thousands of lines of code to
  34.  * find the ADODB calls and switching to PDO.  (I've had to do it twice on the same
  35.  * project, it sucks).  By using this class, I was able to make changes to the DB
  36.  * system in one place, while the application code remained untouched.
  37.  * 
  38.  * This class is not going to be further extended.  There will not be a Gumbo_Query_PDO,
  39.  * Gumbo_Query_ADODB, etc.  Since a large majority of applications will use one
  40.  * database connection, I feel it's better just to have one implementation.  In order
  41.  * to use other DB systems, simply change the implementation for your
  42.  * specific needs (place inside the 'Custom' directory).  The system will load the
  43.  * 'custom' class first, ignoring this one.  Since there is only one, any changes
  44.  * would be made to the implementation, not the application.
  45.  * 
  46.  * (This topic is certainly up for debate, so feel free to post your opinion on the
  47.  * SourceForge Project Forum)
  48.  *
  49.  * @category Gumbo
  50.  * @package Query
  51.  * @copyright Copyright (c) 2007, iBayou, Michael Luster
  52.  * @license http://www.opensource.org/licenses/bsd-license.php New BSD License
  53.  * @author Michael Luster <mluster79@yahoo.com>
  54.  * @link http://sourceforge.net/projects/phpgumbo
  55.  * @desc Query Class
  56.  * @version 0.0.1
  57.  */
  58.  
  59. gumbo_load ("Interface_Singleton");
  60.  
  61. class Gumbo_Query implements Gumbo_Interface_Singleton {
  62.  
  63.     /** @var Gumbo_Interface_Query $_private */
  64.     private static $_instance null;
  65.     
  66.     /** @var mixed $_db Database Abstraction Object (default implementation for PDO) */
  67.     private $_db;
  68.     /** @var string $_token replacement token character for the prepare method */
  69.     private $_token = "?";
  70.     
  71.     
  72.     
  73.     /**
  74.      * Constructor
  75.      */
  76.     private function __construct ({}
  77.     
  78.     /**
  79.      * Singleton Method
  80.      * @return Gumbo_Query 
  81.      */
  82.     public static function instance ({
  83.         if (self::$_instance == null{
  84.             self::$_instance new Gumbo_Query ();
  85.         }
  86.         return self::$_instance;
  87.     }
  88.     
  89.     
  90.     
  91.     /** ACTION METHODS **/
  92.     /**
  93.      * Returns an array of Items with the results of a "SELECT ... " query
  94.      * @precondition getDb()
  95.      * @param string $sql query to execute
  96.      * @param array $params token parameter values
  97.      * @return array 
  98.      * @throws Gumbo_Exception
  99.      */
  100.     public static function results ($sql$params=null{
  101.         $info array ();
  102.         try {
  103.             // verify precondition
  104.             if (!is_string ($sql)) {
  105.                 throw new Gumbo_Exception ("Invalid Argument 'sql:str' => {$sql}:gettype ($sql));
  106.             }
  107.             if (strtolower (substr ($sql06)) != "select"{
  108.                 throw new Gumbo_Exception ("Must Be SELECT Query: {$sql}");
  109.             }
  110.             if (!Gumbo_Query::instance ()->getDb ()) {
  111.                 throw new Gumbo_Exception ("DB Engine Undefined");
  112.             }
  113.             
  114.             // prepare the query
  115.             $sql Gumbo_Query::prepare ($sql$params);
  116.             if (!$sql{
  117.                 return $info;
  118.             }
  119.             
  120.             // execute query, return results as associative array
  121.             return Gumbo_Query::instance ()->getDb ()->query ($sql)->fetch (PDO::FETCH_ASSOC);
  122.         catch (Gumbo_Exception $e{
  123.             $e->setFunction (__METHOD__);
  124.             gumbo_trigger ($e);
  125.         }
  126.         return $info;
  127.     }
  128.     
  129.     /**
  130.      * Executes the given query and returns the results
  131.      * 
  132.      * This is a Bridge between the DB interface and the Item class.  It
  133.      * will execute a sinle query and return the results.  If a SELECT
  134.      * is performed, then a single associative array representing a
  135.      * record is returned.  If an INSERT is performed, then the new insert
  136.      * ID is returned.  UPDATE and DELETE queries will not return anything.
  137.      * 
  138.      * @param string $sql 
  139.      * @param array $params list of parameters for the prepare method
  140.      * @param string $name sequence/column name for returning lastInsertId()
  141.      * @return mixed 
  142.      * @throws Gumbo_Exception
  143.      * @todo implementation for DB classes
  144.      */
  145.     public static function execute ($sql$params=null$name=null{
  146.         try {
  147.             // verify precondition
  148.             if (!is_string ($sql)) {
  149.                 throw new Gumbo_Exception ("Invalid Argument 'sql:str' => {$sql}:gettype ($sql));
  150.             }
  151.             if (is_null ($params|| ($params == false)) $params array ()}
  152.             if (!is_array ($params)) {
  153.                 throw new Gumbo_Exception ("Invalid Argument 'params:arr' => {$params}:gettype ($params));
  154.             }
  155.             if (!is_null ($name&& !is_string ($name)) {
  156.                 throw new Gumbo_Exception ("Invalid Argument 'name:str' => {$name}:gettype ($name));
  157.             }
  158.             if (!Gumbo_Query::instance ()->getDb ()) {
  159.                 throw new Gumbo_Exception ("DB Engine Undefined");
  160.             }
  161.             
  162.             $sql_type strtolower (substr ($sql06));
  163.             
  164.             // check for a SELECT query
  165.             if ($sql_type == "select"{
  166.                 return Gumbo_Query::results ($sql$params);
  167.             }
  168.             
  169.             $sql Gumbo_Query::prepare ($sql$params);
  170.             if (!$sqlreturn null}
  171.             
  172.             // check for an INSERT query
  173.             if ($sql_type == "insert"{
  174.                 // @todo execute query, return new ID
  175.                 Gumbo_Query::instance ()->getDb ()->exec ($sql);
  176.                 return Gumbo_Query::instance ()->getDb ()->lastInsertId ($name);
  177.             }
  178.             
  179.             // check for an UPDATE or DELETE query
  180.             if ($sql_type == "update" || $sql_type == "delete"{
  181.                 // @todo execute query, return affected rows
  182.                 return Gumbo_Query::instance ()->getDb ()->exec ($sql);
  183.             }
  184.             
  185.             // @todo execute query, return results
  186.             return Gumbo_Query::instance ()->getDb ()->query ($sql);
  187.             
  188.         catch (Gumbo_Exception $e{
  189.             $e->setFunction (__METHOD__);
  190.             gumbo_trigger ($e);
  191.         }
  192.     }
  193.     
  194.     /**
  195.      * Prepares a query by substituting a token character with parameter values
  196.      * @param string $sql 
  197.      * @param array $params list of parameters
  198.      * @param string $token replacement token character
  199.      * @return string 
  200.      * @throws Gumbo_Exception
  201.      */
  202.     public static function prepare ($sql$params=null$token=null{
  203.         try {
  204.             // verify precondition
  205.             if (!is_string ($sql)) {
  206.                 throw new Gumbo_Exception ("Invalid Argument 'sql:str' => {$sql}:gettype ($sql));
  207.             }
  208.             if (is_null ($params|| ($params == false)) $params array ()}
  209.             if (!is_array ($params)) {
  210.                 throw new Gumbo_Exception ("Invalid Argument 'params:arr' => {$params}:gettype ($params));
  211.             }
  212.             if (is_null ($token)) $token Gumbo_Query::instance ()->getToken ()}
  213.             if (!is_null ($token&& !is_string ($token)) {
  214.                 throw new Gumbo_Exception ("Invalid Argument 'token:str' => {$token}:gettype ($token));
  215.             }
  216.             
  217.             if (count ($params0{
  218.                 $tokens explode ($token$sql);
  219.                 if (count ($paramscount ($tokens1{
  220.                     throw new Gumbo_Exception ("Invalid Token Countfor: {$sql} for count ($params" Parameters");
  221.                 }
  222.                 
  223.                 $sql null;
  224.                 foreach ($tokens as $key=>$val{
  225.                     $sql .= $val;
  226.                     if (isset ($params [$key])) {
  227.                         if (is_numeric ($params [$key])) $sql .= $params [$key]}
  228.                         if (is_string ($params [$key])) $sql .= "'" addslashes ($params [$key]"'"}
  229.                     }
  230.                 }
  231.             }
  232.             
  233.             return $sql;
  234.         catch (Gumbo_Exception $e{
  235.             $e->setFunction (__METHOD__);
  236.             gumbo_trigger ($e);
  237.         }
  238.         return null;
  239.     }
  240.     
  241.     
  242.     
  243.     /** MUTATOR METHODS **/
  244.     /**
  245.      * Sets the DB Object Reference
  246.      * @param mixed $db 
  247.      */
  248.     public function setDb ($db{
  249.         $this->_db = $db;
  250.     }
  251.     
  252.     /**
  253.      * Sets the token character
  254.      * @param string $token 
  255.      * @throws Gumbo_Exception
  256.      */
  257.     public function setToken ($token{
  258.         try {
  259.             // verify precondition
  260.             if (!is_string ($token)) {
  261.                 throw new Gumbo_Exception ("Invalid Argument 'token:str' => {$token}:gettype ($token));
  262.             }
  263.             
  264.             $this->_token = $token;
  265.         catch (Gumbo_Exception $e{
  266.             $e->setFunction (__METHOD__);
  267.             gumbo_trigger ($e);
  268.         }
  269.     }
  270.     
  271.     
  272.     
  273.     /** ACCESSOR METHODS **/
  274.     /**
  275.      * Returns the DB Resource or Object
  276.      * @return mixed 
  277.      */
  278.     public static function getDb ({
  279.         return $this->_db;
  280.     }
  281.     
  282.     /**
  283.      * Returns the token character
  284.      * @return string 
  285.      */
  286.     public static function getToken ({
  287.         return $this->_token;
  288.     }
  289.     
  290. }
  291.  
  292. ?>