Source for file database.php

Documentation is available at database.php

  1. <?php
  2. /**
  3.  * Database class for all database queries
  4.  *
  5.  * This database class is free software; you can redistribute
  6.  * it and/or modify it under the terms of the GNU
  7.  * General Public License as published by the Free
  8.  * Software Foundation; either version 3 of the License,
  9.  * or (at your option) any later version.
  10.  *
  11.  * This database class is distributed in the hope that it will
  12.  * be useful, but WITHOUT ANY WARRANTY; without even the
  13.  * implied warranty of MERCHANTABILITY or FITNESS FOR A
  14.  * PARTICULAR PURPOSE.  See the GNU General Public
  15.  * License for more details.
  16.  *
  17.  *
  18.  * @author Andrew Judd <andrew@andrewjudd.ca>
  19.  * @copyright Andrew Judd, 2009
  20.  * @license http://www.gnu.org/licenses/gpl-3.0.txt GPLv3
  21.  * @package Databases
  22.  * @version 2.2.8
  23.  *
  24.  *  For full documentation and updates please visit:
  25.  *  http://development.andrewjudd.ca
  26.  *
  27.  *  Version Updates:<br /><br />
  28.  *  2.0.0:<br />
  29.  *  This updated version of the database class uses PDO and PDO Statements
  30.  *  as the basis for all of the database queries.  This will increase the
  31.  *  security of the script as well as the ability for the script.<br /><br />
  32.  *
  33.  *  2.0.1:<br />
  34.  *  Added in %p for signed/unsigned decimal values.<br /><br />
  35.  *
  36.  *  2.1.0:<br />
  37.  *  All error messages are appended onto each other before the query is complete.
  38.  *  <br /><br />
  39.  *
  40.  *  2.2.0:<br />
  41.  *  - Added the ability to track the total amount of time for all queries<br />
  42.  *  - Added a count of the number of successful queries which were run<br />
  43.  *  - Added the ability to log all queries with their associated times
  44.  *  <br /><br />
  45.  *
  46.  *  2.2.1:<br />
  47.  *  Fixed a bug that was making it so that numRows didn't actually work
  48.  *  properly/as expected.
  49.  *  <br /><br />
  50.  *
  51.  *  2.2.2:<br />
  52.  *  - Added in %i for IP addresses<br />
  53.  *  - Added in extra error checking on the getArray function
  54.  *  <br /><br />
  55.  *
  56.  *  2.2.3:<br />
  57.  *  - Added in %b for binary files
  58.  *  <br /><br />
  59.  *
  60.  *  2.2.4:<br />
  61.  *  - Added the ability to view error messages that are sent back from the
  62.  *        database for more information about what went wrong with the query.
  63.  *  <br /><br />
  64.  *
  65.  *  2.2.5:<br />
  66.  *  - Freed some memory when you close the cursor<br />
  67.  *  - Added the 'getInsertId' function
  68.  *
  69.  *  2.2.6:<br />
  70.  *  - Fixed a bug which wasn't allowing a NULL username or password (changed the
  71.  *        default values to empty)
  72.  *
  73.  *  2.2.7:<br />
  74.  *  - Added a getNumAffected function in order to determine how many rows were
  75.  *    affected by the query which was run.
  76.  *  - Changed printLog so that it has valid HTML (inline css rather than external)
  77.  *
  78.  *  2.2.8:<br />
  79.  *  - Added in the line number into the invalid data type messages
  80.  */
  81. class database
  82. {
  83.         /**
  84.          * Used to symbolise whether or not a connection to the database has been
  85.          * made.
  86.          */
  87.         private $connected;
  88.  
  89.         /**
  90.          * Used to symbolise if Verbose mode is on or off.
  91.          */
  92.         private $verbose;
  93.        
  94.         /**
  95.          * Used to store the connection to the database
  96.          */
  97.         private $connection;
  98.        
  99.         /**
  100.          * Used to store the total amount of time that the database options required
  101.          */
  102.         private $totalTime;
  103.        
  104.         /**
  105.          * Used to maintain a count of the number of SUCCESSFUL queries that were
  106.          * executed.
  107.          */
  108.         private $queryCount;
  109.        
  110.         /**
  111.          * Used to determine if we should be logging the queries that get executed.
  112.          */
  113.         private $logQueries;
  114.        
  115.         /**
  116.          * Used to hold the log of all the queries that were executed along with how
  117.          * long it took them to be executed.
  118.          */
  119.         private $log;
  120.        
  121.         /**
  122.          * Used to hold a list of any exceptions that are thrown.
  123.          */
  124.         private $errorMessages;
  125.  
  126.         /* Create the database object */
  127.        
  128.         /**
  129.          * This is the two argument constructor for the database
  130.          * connection object.  This will create the database connection
  131.          * if possible or if it fails it will set the 'connected' flag to
  132.          * false indicating that we aren't connected to the database.
  133.          * @param $connInfo The connection information about how to connect to the
  134.          *               database.  This value should be an array setup in the following
  135.          *               fashion.
  136.          *               array ( "host" => "hostname", "name" => "database_name",
  137.          *                               "user" => "username", "pass" => "password" )
  138.          *               If this array is NULL or any of the elements are missing, then they
  139.          *               will be defaulted to the values as specified in the constructor.
  140.          * @param $connType The type of database that we are connecting to
  141.          */
  142.         public function __construct $connInfo null$connType "mysql" )
  143.         {
  144.                 /* Get database username and password information */
  145.                 $db_host "hostname"/* Normally 'localhost' */
  146.                 $db_name "database_name";
  147.                 $db_user '';
  148.                 $db_pass '';
  149.                
  150.                 /* Check if they specified any of the information */
  151.                 if $connInfo != NULL )
  152.                 {
  153.                         /* If they have let's see if there is any information */
  154.                        
  155.                         if isset $connInfo 'host' ) )
  156.                         {
  157.                                 $db_host $connInfo 'host' ];
  158.                         }
  159.                        
  160.                         if isset $connInfo 'name' ) )
  161.                         {
  162.                                 $db_name $connInfo 'name' ];
  163.                         }
  164.  
  165.                         if isset $connInfo 'user' ) )
  166.                         {
  167.                                 $db_user $connInfo 'user' ];
  168.                         }
  169.                        
  170.                         if isset $connInfo 'pass' ) )
  171.                         {
  172.                                 $db_pass $connInfo 'pass' ];
  173.                         }
  174.                 }
  175.        
  176.                 /* Assume we are connected and turn off verbose mode */
  177.                 $this -> connected = true;
  178.                
  179.                 /* Turn off verbose mode so error messages won't show up */
  180.                 $this -> setVerbose false );
  181.                
  182.                 /* Initialize the amount of time taken */
  183.                 $this -> totalTime = 0;
  184.                
  185.                 /* Initialize the number of queries executed */
  186.                 $this -> queryCount = 0;
  187.                
  188.                 /* Turn off the logging in the beginning */
  189.                 $this -> setLogging false );
  190.                
  191.                 /* Initialize the array for storing the logs as empty */
  192.                 $this -> log = array ();
  193.                
  194.                 /* Initialize the array for store the error messages */
  195.                 $this -> errorMessages = array ();
  196.        
  197.                 /* Try to connect to the database */
  198.                 try
  199.                 {
  200.                         $start microtime ();
  201.                         $this -> connection = new PDO "$connType:host=$db_host;dbname=$db_name",
  202.                                 $db_user$db_pass );
  203.                                
  204.                         /* The amount of time it took to connect to the database */
  205.                         $length microtime ($start;
  206.                                
  207.                         /* Add the time spent trying to connect to the database */
  208.                         $this -> addTime $length );
  209.                        
  210.                         /* Add it to the log */
  211.                         $this -> appendToLog "<em>Connection Created</em>"$length );
  212.                        
  213.                         /* Throw an exception whenever there is a problem */
  214.                         $this -> connection -> setAttribute PDO::ATTR_ERRMODE,
  215.                                 PDO::ERRMODE_EXCEPTION);
  216.                 }
  217.                 catch PDOException $e )
  218.                 {
  219.                         $this -> connected = false;
  220.                         $this -> connection = NULL;
  221.                        
  222.                         $this -> setVerbose true );
  223.                         $this -> error $e -> getMessage () );
  224.                         $this -> setVerbose false );
  225.                 }
  226.         }
  227.        
  228.         /**
  229.          * This function is used in order to free the results from the query that is
  230.          * passed in as the argument.
  231.          *
  232.          * @param array $res The result set to clear
  233.          */
  234.         public function freeResults array $res )
  235.         {
  236.                 /* Validate the data set */
  237.                 if $this -> validateResultSet $res === FALSE )
  238.                 {
  239.                         return NULL );
  240.                 }
  241.        
  242.                 $res -> closeCursor ();
  243.                
  244.                 /* Free everything in the array */
  245.                 foreach $res as $toFree )
  246.                 {
  247.                         unset $toFree );
  248.                 }
  249.                
  250.                 return NULL );
  251.         }
  252.        
  253.         /**
  254.          * This function is the starting function for the query that is being run.
  255.          * It will take in the query with the following values for the parameters
  256.          * and then insert the values in their corresponding spots after making
  257.          * sure that the data passed in matches the correct data type (based on
  258.          * regular expression).<br /><br />
  259.          * The following are parameter types for the values:
  260.          * <ul>
  261.          * <li>%u - unsigned integer - ^[0-9]+$</li>
  262.          * <li>%d - signed integer - ^[-+]?[0-9]+$</li>
  263.          * <li>%p - decimal number - ^[-+]?[0-9]+(\.[0-9]+)?$</li>
  264.          * <li>%s - string (no HTML permitted)</li>
  265.          * <li>%h - string (HTML permitted)</li>
  266.          * <li>%l - list of strings (comma separated) or an array (no HTML permitted)</li>
  267.          * <li>%i - IP Address - ^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$</li>
  268.          * <li>%b - Binary Files</li>
  269.          * <li>%f - field</li>
  270.          * </ul>
  271.          * The number of arguments passed into this function is required to be
  272.          * directly related to the number of parameters included in the query.
  273.          * For example, if there are two parameters in the query then there should
  274.          * be three arguments for the function (one argument for the query and two
  275.          * arguments for the necessary parameters).
  276.          *
  277.          * Example of how to use the parameters in a query:
  278.          * $db = new database (); //make the database connection<br />
  279.          * $result = $db -> query ( "SELECT * FROM `members` WHERE `id` = %u AND `username` = %s",
  280.          *                              $user_id, $username ); //Create the query<br />
  281.          * The query will validate the variable $user_id will be validated as an
  282.          * unsigned integer and the $username will be validated as a string.
  283.          *
  284.          * @param $query The query that we will be building on
  285.          * @param $args1-X All of the corresponding values for the query (the number
  286.          *                                 of these is based on however many parameters there are in
  287.          *                                 the database query)
  288.          * @return This function will either return a PDO Statement which has been
  289.          *                  executed (if all validation is successful) or NULL
  290.          *                  NULL will be returned in the following cases:
  291.          *                       <ul>
  292.          *                       <li>No database connection</li>
  293.          *                       <li>Too few arguments</li>
  294.          *                       <li>Too many arguments</li>
  295.          *                       <li>Invalid Data Type</li>
  296.          *                       <li>Unknown Parameter Type</li>
  297.          *                       </ul>
  298.          */
  299.         public function query $query )
  300.         {
  301.                 /* Call the backtrace to get the calling function */
  302.                 $backTrace debug_backtrace ();
  303.                 $callingLine $backTrace 'line' ];
  304.  
  305.                 /* Not connected to the database? Return NULL */
  306.                 if $this -> connected == false )
  307.                 {
  308.                         return NULL );
  309.                 }
  310.        
  311.                 /* Stores the position of each "%" value */
  312.                 $last 0;
  313.  
  314.                 /* Stores all of the information about where they occur */
  315.                 $where array ();
  316.                
  317.                 /* Stores information about the query parameters for use with PDO */
  318.                 $queryParams array ();
  319.                
  320.                 if is_array $query === TRUE )
  321.                 {
  322.                         $args $query;
  323.                         $query $query ];
  324.                 }
  325.                 else
  326.                 {
  327.                         $args func_get_args ();
  328.                 }
  329.                
  330.                 /* Hold an unmodified version of the query in case we want to log it */
  331.                 $holdQuery $query;
  332.  
  333.                 /* Read in each and every query parameter and store it's relative position
  334.                  * along with the type.
  335.                  */
  336.                 while ( ( $last strpos $query"%"$last ) ) != false )
  337.                 {
  338.                         $where [array 'start' => $last'type' => substr $query$last) );
  339.                 }
  340.                
  341.                 /* Read in each of the arguments for the function */
  342.                 //$args = func_get_args ();
  343.                
  344.                 /* Figure out how many arguments there are */
  345.                 $numArgs count $args 1;
  346.                
  347.                 /* Check if there enough parameters */
  348.                 if $numArgs count $where ) )
  349.                 {
  350.                         /*
  351.                          * Too few parameters so if verbose mode is on then we'll let the
  352.                          * developer know.
  353.                          */
  354.                          $errorMessage "$query<br />There are too few parameters (add ".count $where $numArgs )." argument[s]).";
  355.                         
  356.                         $this -> error $errorMessage );
  357.                        
  358.                         /* Terminate the Query function because we don't have enough information */
  359.                         return null );
  360.                 }
  361.                 else if $numArgs count $where ) )
  362.                 {
  363.                         /*
  364.                          * Too many parameters so if verbose mode is on then we'll let the
  365.                          * developer know.
  366.                          */
  367.                        
  368.                         $errorMessage "$query<br />There are too many parameters (remove ".count $where $numArgs )." argument[s])." ;
  369.                         $this -> error $errorMessage );
  370.                        
  371.                         /* Terminate the query function because we have too much information */
  372.                         return null );
  373.                 }
  374.                
  375.                 $x 0;
  376.                 $len count $where );
  377.                
  378.                 $errorMessage "";
  379.                
  380.                 /* Cycle through all of the parameters */
  381.                 for $x 0$x $len$x++ )
  382.                 {
  383.                         /* Grab the type associated with it */
  384.                         $type $where $x 'type' ];
  385.                        
  386.                         switch $type )
  387.                         {
  388.                                 case "%u":
  389.                                         if preg_match "/^[0-9]+$/"$args $x ) )
  390.                                         {
  391.                                                 $errorMessage .= "<li>Invalid unsigned number (".
  392.                                                         $args $x ].") on line number " $callingLine"</li>";
  393.                                         }
  394.                                         $args $x $args $x ];
  395.                                         break;
  396.                                 case "%d":
  397.                                         if preg_match "/^[-+]?[0-9]+$/"$args $x ) )
  398.                                         {
  399.                                                 $errorMessage .= "<li>Invalid signed number (".
  400.                                                         $args $x ].") on line number " $callingLine "</li>" ;
  401.                                         }
  402.                                         $args $x $args $x ];
  403.                                         break;
  404.                                 case "%p":
  405.                                         if preg_match "/^[-+]?[0-9]+(\.[0-9]+)?$/"$args $x ) )
  406.                                         {
  407.                                                 $errorMessage .= "<li>Invalid signed float (".
  408.                                                         $args $x ].") on line number " $callingLine ".</li>" ;
  409.                                         }
  410.                                         $args $x $args $x ];
  411.                                         break;
  412.                                 case "%s":
  413.                                 case "%l":
  414.                                         /* Check whether or not the value is an array */
  415.                                         if is_array $args $x ) )
  416.                                         {
  417.                                                 /* If it is then remove any HTML tags from each element */
  418.                                                 foreach $args $x as $key => $val )
  419.                                                 {
  420.                                                         $args $x $key htmlentities $val );
  421.                                                 }
  422.                                         }
  423.                                         else
  424.                                         {
  425.                                                 /* Otherwise remove the HTML tags from the one */
  426.                                                 $args $x htmlentities $args $x );
  427.                                         }
  428.                                         break;
  429.                                 case "%h"/* HTML */
  430.                                 case "%b"/* Binary */
  431.                                         /* Do Nothing */
  432.                                         break;
  433.                                 case "%i":
  434.                                         if preg_match "/^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/"$args $x ) )
  435.                                         {
  436.                                                 $errorMessage .= "<li>Invalid IP Address (".
  437.                                                         $args $x ].") on line number " $callingLine ".</li>" ;
  438.                                         }
  439.                                         $args $x $args $x ];
  440.                                         break;
  441.                                 case "%f":
  442.                                         if preg_match "/^[A-Za-z0-9_]+$/"$args $x ) )
  443.                                         {
  444.                                                 $errorMessage .= "<li>Invalid field name (".
  445.                                                         $args $x ].") on line number " $callingLine ".</li>" ;
  446.                                         }
  447.                                         $args $x "`".$args $x ]."`";
  448.                                         break;
  449.                                 default:
  450.                                         $errorMessage .= "<li>Unknown Parameter '$type'.</li>;
  451.                         }
  452.                        
  453.                         if isset $args $x ) )
  454.                         {
  455.                                 if $type == "%f" )
  456.                                 {
  457.                                         $query preg_replace "/$type/"$args $x $query);
  458.                                 }
  459.                                 else if $type == "%l" )
  460.                                 {
  461.                                         /* Check if it was an array passed in */
  462.                                         if is_array $args $x ) )
  463.                                         {
  464.                                                 /*
  465.                                                  * If it wasn't then we must be a list so break it into
  466.                                                  * an array and count how many elements there are.
  467.                                                  */
  468.                                                 $count count explode ","$args $x ) );
  469.                                         }
  470.                                         else
  471.                                         {
  472.                                                 /* Otherwise just count the elements */
  473.                                                 $count count $args $x );
  474.                                         }
  475.  
  476.                                         /* Initialize the 2 variables for building the string */
  477.                                         $build "";
  478.                                         $commas "";
  479.                                        
  480.                                         /* Build the string for the parameters */
  481.                                         for $y 0$y $count$y++ )
  482.                                         {
  483.                                                 /*
  484.                                                  * On the builded string append potentially a comma and
  485.                                                  * a '?' for the parameter
  486.                                                  */
  487.                                                 $build .= $commas."?";
  488.                                                 $commas ",";
  489.                                         }
  490.                                        
  491.                                         /* Put the newly built string into the query */
  492.                                         $query preg_replace "/$type/"$build $query);
  493.                                         $queryParams [array $type$args $x );
  494.                                 }
  495.                                 else
  496.                                 {
  497.                                         $query preg_replace "/$type/""?" $query);
  498.                                         $queryParams [array $type$args $x );
  499.                                 }
  500.                         }
  501.                 }
  502.                
  503.                 /* If there is at least 1 error message */
  504.                 if $errorMessage != "" )
  505.                 {
  506.                         $errorMessage "There were the following errors with your query:".
  507.                                 "<ul>$errorMessage</ul>";
  508.                                
  509.                         $this -> error $errorMessage );
  510.                         return NULL );
  511.                 }
  512.                
  513.                 $start microtime ();
  514.                 /* Prepare the database statement */
  515.                 $statement $this -> getDatabaseConnection (-> prepare $query );
  516.  
  517.                 for $x 1$x <= count $queryParams )$x++ )
  518.                 {
  519.                         switch $queryParams $x )
  520.                         {
  521.                                 case "%u":
  522.                                 case "%d":
  523.                                         $statement -> bindParam $xintval($queryParams $x ]),
  524.                                                 PDO::PARAM_INT );
  525.                                         break;
  526.                                 case "%s":
  527.                                 case "%h":
  528.                                 case "%i":
  529.                                         $statement -> bindParam $x$queryParams $x ],
  530.                                                 PDO::PARAM_STRstrlen $queryParams $x ) );
  531.                                         break;
  532.                                 case "%p":
  533.                                         $statement -> bindParam $xfloatval($queryParams $x ]) );
  534.                                         break;
  535.                                 case "%b":
  536.                                         $statement -> bindParam $x$queryParams $x ]PDO::PARAM_LOB );
  537.                                         break;
  538.                                 case "%l":
  539.                                         /* Check if it was an array passed in */
  540.                                         if !is_array $queryParams $x ) )
  541.                                         {
  542.                                                 /*
  543.                                                  * If it wasn't then we must be a list so break it into
  544.                                                  * an array.
  545.                                                  */
  546.                                                 $params explode ","$queryParams $x );
  547.                                         }
  548.                                         else
  549.                                         {
  550.                                                 /* Otherwise just grab the passed in array */
  551.                                                 $params $queryParams $x ];
  552.                                         }
  553.                                        
  554.                                         /* Count the elements */
  555.                                         $num count $params );
  556.                                        
  557.                                         for $y 0$y $num$y++ )
  558.                                         {
  559.                                                 /* Bind each of the parameters to the query */
  560.                                                 $statement -> bindParam $x$params $y ],
  561.                                                         PDO::PARAM_STRstrlen $params $y ) );
  562.                                                 $x++;
  563.                                         }
  564.                         }
  565.                 }
  566.  
  567.                 try
  568.                 {
  569.                         /* Execute the database query */
  570.                         $statement -> execute ();
  571.                 }
  572.                 catch PDOException $e )
  573.                 {
  574.                         $this -> setErrorMessage $args$e );
  575.                 }
  576.                
  577.                 /* Calculate how long the query took */
  578.                 $length microtime ($start;
  579.                
  580.                 /* Add the time for executing the single query */
  581.                 $this -> addTime $length );
  582.                
  583.                 /* Check if we are logging all queries */
  584.                 if $this -> getLogging (=== TRUE )
  585.                 {
  586.                         /* If we are then add it */
  587.                         $this -> appendToLog $holdQuery$length );
  588.                 }
  589.                
  590.                 /* Add 1 to the query count */
  591.                 $this -> queryCount += 1;
  592.                
  593.                 /* If the query didn't faile */
  594.                 if $statement != NULL )
  595.                 {
  596.                         /* Grab the Id */
  597.                         $lastIndex $this -> connection -> lastInsertId ();
  598.                 }
  599.                
  600.                 $ret array $statementfunc_get_args ()$lastIndex );
  601.                
  602.                 return $ret );
  603.         }
  604.        
  605.         /**
  606.          * This function is used in order to display an error message about what went
  607.          * wrong within the query.
  608.          * @param $text - The text that the error messsage will display
  609.          */
  610.         private function error $text )
  611.         {
  612.                 if $this -> getVerbose () )
  613.                 {      
  614.                         echo "<br /><font color = 'red'><b>ERROR</b></font> - $text<br />);
  615.                 }
  616.         }
  617.        
  618.         /**
  619.          * This function is used to set the error message for the specified error.
  620.          * @param $error The information which will be used as the unique key to
  621.          *                                search for the error message with.
  622.          * @param $errorInformation The exception that has been thrown
  623.          */
  624.         private function setErrorMessage $error$errorInformation )
  625.         {
  626.                 $errorId md5 serialize $error ) );
  627.        
  628.                 $this -> errorMessages "$errorId$errorInformation;
  629.         }
  630.        
  631.         /**
  632.          * This function is used in order to retrieve the insert id for the database
  633.          * query that has been run.
  634.          * @param array $res - The statement that has been executed.
  635.          * @return NULL if the statement provided was invalid or the insert id
  636.          */
  637.         public function getInsertId array $res )
  638.         {
  639.                 /* Validate the data set */
  640.                 if $this -> validateResultSet $res === FALSE )
  641.                 {
  642.                         return NULL );
  643.                 }
  644.                
  645.                 /* Return what the value was */
  646.                 return $res );
  647.         }
  648.        
  649.         /**
  650.          * This function is used in order to retrieve the number of rows affected by
  651.          * the database query which was just run.  For UPDATE it returns the number
  652.          * of rows modified, for DELETE it returns the number of rows deleted, etc.
  653.          * @param array $res - The statement that has been executed.
  654.          * @return NULL if the statement provided was invalid or the insert id
  655.          */
  656.         public function getNumAffected array $res )
  657.         {
  658.                 /* Validate the data set */
  659.                 if $this -> validateResultSet $res === FALSE )
  660.                 {
  661.                         return NULL );
  662.                 }
  663.                
  664.                 /* Return what the value was */
  665.                 return $res -> rowCount () );
  666.         }
  667.        
  668.         /**
  669.          * This function is used in order to retrieve the error message which
  670.          * corresponds to the query that was executed.
  671.          * @param array $res - The statement that has been executed.
  672.          * @return NULL if there was no error present or the exception.
  673.          */
  674.         private function getErrorMessage array $res )
  675.         {
  676.                 /* Generate the Hash */
  677.                 $md5 md5 serialize $res ) );
  678.                
  679.                 /* Check if it exists */
  680.                 if isset $this -> errorMessages "$md5=== TRUE )
  681.                 {
  682.                         /* If it does, the return it */
  683.                         return $this -> errorMessages "$md5);
  684.                 }
  685.                 else
  686.                 {
  687.                         /* Otherwise there was no error so return NULL */
  688.                         return NULL );
  689.                 }
  690.         }
  691.        
  692.         /**
  693.          * This function is used in order to retrieve the error that was with a
  694.          * corresponding query (i.e. invalid SQL).
  695.          * @param array $res - The statement that has been executed.
  696.          * @param $onlyMessage If the user only wants the error message returned or
  697.          *                                               not.  This is defaulted to only return the error
  698.          *                                               message.
  699.          * @return Either the string containing the error message or the entire
  700.          *                       exception.
  701.          */
  702.         public function retrieveErrorMessage array $res$onlyMessage TRUE )
  703.         {
  704.                 if $this -> validateResultSet $res === FALSE )
  705.                 {
  706.                         return NULL );
  707.                 }
  708.                
  709.                 /* Grab the error information */
  710.                 $errors $this -> getErrorMessage $res );
  711.        
  712.                 /* Check if an error existed */
  713.                 if $errors == NULL )
  714.                 {
  715.                         /* If there we no problems, then return NULL */
  716.                         return NULL );
  717.                 }
  718.        
  719.                 /* What do we want to send back? */
  720.                 if $onlyMessage === TRUE )
  721.                 {
  722.                         return $errors -> getMessage () );
  723.                 }
  724.                 else
  725.                 {
  726.                         return $errors );
  727.                 }
  728.         }
  729.        
  730.         /**
  731.          * This function is used internally in order to verify that the result set
  732.          * sent in from the user is valid.
  733.          * @param array $res - The statement that has been executed.
  734.          * @return TRUE when the result set is valid FALSE otherwise
  735.          */
  736.         private function validateResultSet array $res )
  737.         {
  738.                 if $res != NULL || is_array $res === FALSE ||
  739.                         $res instanceof PDOStatement === FALSE )
  740.                 {
  741.                         return TRUE );
  742.                 }
  743.                
  744.                 return FALSE );
  745.         }
  746.        
  747.         /**
  748.          * This function is used in order to return the number of rows for a given
  749.          * query.
  750.          * @param $res The statement that has been executed.
  751.          * @return NULL if the parameter is invalid or the number of rows that is with
  752.          *                  the database statement
  753.          */
  754.         public function numRows $res )
  755.         {
  756.                 if $this -> validateResultSet $res === FALSE )
  757.                 {
  758.                         return NULL );
  759.                 }
  760.                
  761.                 $split preg_split "/(FROM)|(ORDER)/"$res );
  762.  
  763.                 $res "SELECT COUNT(*) AS numRows FROM ".$split ];
  764.  
  765.                 $res $this -> query $res );
  766.  
  767.                 $read $this -> getArray $res );
  768.  
  769.                 return $read 'numRows' );
  770.         }
  771.        
  772.         /**
  773.          * This function is used in order to retrieve an associative array from the
  774.          * database statement.
  775.          * @param array $res The result that the 'query' function returned
  776.          * @return The associative array retrieved from the database query or NULL if
  777.          *                       if value passed in was NULL
  778.          */
  779.         public function getArray array $res )
  780.         {
  781.                 if $this -> validateResultSet $res === FALSE )
  782.                 {
  783.                         return NULL );
  784.                 }
  785.        
  786.                 return $res -> fetch PDO::FETCH_ASSOC ) );
  787.         }
  788.        
  789.         /**
  790.          * This function is used in order to determine if Verbose mode is turned on
  791.          * or not.
  792.          * @return TRUE if it is FALSE if it is not
  793.          */
  794.         private function getVerbose ()
  795.         {
  796.                 return $this -> verbose );
  797.         }
  798.        
  799.         /**
  800.          * This function is used in order to set whether or not verbose mode is
  801.          * on or off.
  802.          * @param $verbose TRUE if the verbose mode is to be turned on, FALSE otherwise
  803.          */
  804.         public function setVerbose $verbose )
  805.         {
  806.                 $this -> verbose $verbose;
  807.         }
  808.        
  809.         /**
  810.          * This function is used in order to retrieve an indexed array from the
  811.          * database statement.
  812.          * @param array $res The result that the 'query' function returned
  813.          * @return The indexed array retrieved from the database query or NULL if
  814.          *                       value passed in was NULL
  815.          */
  816.         public function getNumber array $res )
  817.         {
  818.                 if $this -> validateResultSet $res === FALSE )
  819.                 {
  820.                         return NULL );
  821.                 }
  822.        
  823.                 return $res -> fetch PDO::FETCH_NUM ) );
  824.         }
  825.        
  826.         /**
  827.          * This function is used in order to retrieve both the associative array
  828.          * and the indexed array from the database statement.
  829.          * @param array $res - The result that the 'query' function returned
  830.          * @return The associative array and the indexed array retrieved from the
  831.          *                       database query or NULL if value passed in was NULL
  832.          */
  833.         public function getBoth array $res )
  834.         {
  835.                 if $this -> validateResultSet $res === FALSE )
  836.                 {
  837.                         return NULL );
  838.                 }
  839.        
  840.                 return $res -> fetch PDO::FETCH_BOTH ) );
  841.         }
  842.        
  843.         /**
  844.          * This function is used in order to retrieve all of the rows which were
  845.          * obtained by the database query.
  846.          * @param array $res - The result that the 'query' function returned
  847.          * @return An array of all of the results retrieved from the database
  848.          */
  849.         public function retrieveAllRows array $res )
  850.         {
  851.                 if $this -> validateResultSet $res === FALSE )
  852.                 {
  853.                         return NULL );
  854.                 }
  855.                
  856.                 return $res -> fetchAll () );
  857.         }
  858.        
  859.         /**
  860.          * This function is used in order to retrieve the actual database connection
  861.          * that was created on instantiation of the object.
  862.          * @return The database connection object
  863.          */
  864.         public function getDatabaseConnection ()
  865.         {
  866.                 return $this -> connection );
  867.         }
  868.        
  869.         /**
  870.          * This function is used in order to start a transaction so that the set of
  871.          * queries can be rolled back or committed at any time.
  872.          * @return TRUE on success, FALSE on failure
  873.          */
  874.         public function startTransaction ()
  875.         {
  876.                 $start microtime ();
  877.        
  878.                 try
  879.                 {
  880.                         /* Begin a transaction on the database */
  881.                         $this -> connection -> beginTransaction ();
  882.                 }
  883.                 catch PDOException $e )
  884.                 {
  885.                         /* Calculate how long the query took */
  886.                         $length microtime ($start;
  887.                        
  888.                         /* Check if we are keeping a log of all of the queries */
  889.                         if $this -> getLogging (=== TRUE )
  890.                         {
  891.                                 /* If we are then add a new record to the log */
  892.                                 $this -> appendToLog "<em>Failed to start transaction</em>"$length );
  893.                         }
  894.                        
  895.                         /* The commit failed so return false */
  896.                         return FALSE );
  897.                 }
  898.                
  899.                 /* Calculate how long the query took */
  900.                 $length microtime ($start;
  901.                
  902.                 /* Check if we are keeping a log of all of the queries */
  903.                 if $this -> getLogging (=== TRUE )
  904.                 {
  905.                         /* If we are then add a new record to the log */
  906.                         $this -> appendToLog "<em>Started Transaction</em>"$length );
  907.                 }
  908.                
  909.                 return TRUE );
  910.         }
  911.        
  912.         /**
  913.          * This function is used in order to rollback any queries which were executed
  914.          * on the database.
  915.          * @return TRUE on success, FALSE on failure
  916.          */
  917.         public function rollback ()
  918.         {
  919.                 $start microtime ();
  920.        
  921.                 try
  922.                 {
  923.                         /* Rollback the changes to the database */
  924.                         $this -> connection -> rollback ();
  925.                 }
  926.                 catch PDOException $e )
  927.                 {
  928.                         /* Calculate how long the query took */
  929.                         $length microtime ($start;
  930.                        
  931.                         /* Check if we are keeping a log of all of the queries */
  932.                         if $this -> getLogging (=== TRUE )
  933.                         {
  934.                                 /* If we are then add a new record to the log */
  935.                                 $this -> appendToLog "<em>Failed Rollback</em>"$length );
  936.                         }
  937.                        
  938.                         /* The commit failed so return false */
  939.                         return FALSE );
  940.                 }
  941.                
  942.                 /* Calculate how long the query took */
  943.                 $length microtime ($start;
  944.                
  945.                 /* Check if we are keeping a log of all of the queries */
  946.                 if $this -> getLogging (=== TRUE )
  947.                 {
  948.                         /* If we are then add a new record to the log */
  949.                         $this -> appendToLog "<em>Successful Rollback</em>"$length );
  950.                 }
  951.                
  952.                 return TRUE );
  953.         }
  954.        
  955.         /**
  956.          * This function is used in order to commit all of the queries which were
  957.          * executed on the database to the database.
  958.          * @return TRUE on success, FALSE on failure
  959.          */
  960.         public function commit ()
  961.         {
  962.                 $start microtime ();
  963.                
  964.                 try
  965.                 {
  966.                         /* Commit the changes to the database */
  967.                         $this -> connection -> commit ();
  968.                 }
  969.                 catch PDOException $e )
  970.                 {
  971.                         /* Calculate how long the query took */
  972.                         $length microtime ($start;
  973.                        
  974.                         /* Check if we are keeping a log of all of the queries */
  975.                         if $this -> getLogging (=== TRUE )
  976.                         {
  977.                                 /* If we are then add a new record to the log */
  978.                                 $this -> appendToLog "<em>Failed Commit</em>"$length );
  979.                         }
  980.                        
  981.                         /* The commit failed so return false */
  982.                         return FALSE );
  983.                 }
  984.                
  985.                 /* Calculate how long the query took */
  986.                 $length microtime ($start;
  987.                
  988.                 /* Check if we are keeping a log of all of the queries */
  989.                 if $this -> getLogging (=== TRUE )
  990.                 {
  991.                         /* If we are then add a new record to the log */
  992.                         $this -> appendToLog "<em>Successful Commit</em>"$length );
  993.                 }
  994.                
  995.                 return TRUE );
  996.         }
  997.        
  998.         /**
  999.          * This function is used in order to retrieve the total amount of time it took to
  1000.          * execute all of the queries on the database.
  1001.          * @param $dp How many decimal places to round the number to, ignore this
  1002.          *               parameter if you do not want to round the number, otherwise if
  1003.          *               invalid then NULL will be returned.
  1004.          * @return The total amount of time taken to execute all of the database queries
  1005.          *          in microseconds.
  1006.          */
  1007.         public function getTotalTime $dp null )
  1008.         {
  1009.                 if is_numeric $dp && $dp >= )
  1010.                 {
  1011.                         return round $this -> totalTime$dp ) );
  1012.                 }
  1013.                 elseif $dp == null )
  1014.                 {
  1015.                         return $this -> totalTime );
  1016.                 }
  1017.                
  1018.                 return NULL );
  1019.         }
  1020.        
  1021.         /**
  1022.          * This function is used in order to add more time to the total time that the
  1023.          * script spent on database processing.
  1024.          * @param $amount The amount of time to add to the total time spent querying the
  1025.          *                 database.
  1026.          */
  1027.         private function addTime $amount )
  1028.         {
  1029.                 $this -> totalTime += $amount;
  1030.         }
  1031.        
  1032.         /**
  1033.          * This function is used in order to retrieve the number of queries which
  1034.          * were executed on the database.
  1035.          * @return The number of successful queries executed on the database
  1036.          */
  1037.         public function retrieveNumberOfQueries ()
  1038.         {
  1039.                 return $this -> queryCount );
  1040.         }
  1041.        
  1042.         /**<em>
  1043.          * This function is used in order to turn on/off the query logging functionality.
  1044.          * @param $value Either TRUE or FALSE depending if you want all queries to be
  1045.          *                               logged (TRUE they will be, FALSE they will not be)
  1046.          */
  1047.         public function setLogging $value )
  1048.         {
  1049.                 if $value === TRUE || $value === FALSE )
  1050.                 {
  1051.                         $this -> logQueries $value;
  1052.                 }
  1053.         }
  1054.        
  1055.         /**
  1056.          * This function is used in order to determine if we are keeping logs of all
  1057.          * of the queries that occur.
  1058.          * @return TRUE if we are logging all of the queries, FALSE if we are not
  1059.          */
  1060.         public function getLogging ()
  1061.         {
  1062.                 return $this -> logQueries );
  1063.         }
  1064.        
  1065.         /**
  1066.          * This function is used in order to add the query to the list of all queries
  1067.          * which were executed.
  1068.          * @param $query The query that was executed
  1069.          * @param $time The amount of time it took for the query to be executed
  1070.          */
  1071.         private function appendToLog $query$time )
  1072.         {
  1073.                 $this -> log [array "query" => $query"time" => $time );
  1074.         }
  1075.        
  1076.         /**
  1077.          * This function is used in order to retrieve the raw version of the log
  1078.          * (the array that actually holds the log).
  1079.          * @return The array containing the actual log
  1080.          */
  1081.         public function retrieveLog ()
  1082.         {
  1083.                 return $this -> log );
  1084.         }
  1085.        
  1086.         /**
  1087.          * This function is used in order to display the log in a more useful manner.
  1088.          * This function will output the information directly onto the page.
  1089.          */
  1090.         public function printLog ()
  1091.         {
  1092.                 echo "\n\n<table style = \"width: 75%; border: 1px solid black;" );
  1093.                 echo " border-collapse: collapse;\">" );
  1094.                
  1095.                 echo "\n\t<tr>" );
  1096.                 echo "\n\t<th style = 'border: 1px solid black; padding: 5px;'>Query</th>" );
  1097.                 echo "\n\t<th style = 'border: 1px solid black; padding: 5px;'>Time (milliseconds)</th>" );
  1098.                 echo "\n\t</tr>" );
  1099.                
  1100.                 foreach $this -> retrieveLog (as $entry )
  1101.                 {
  1102.                         echo "\n\t<tr>" );
  1103.                        
  1104.                         echo "\n\t\t<td style = 'border: 1px solid black; padding: 5px;'>".
  1105.                                 $entry 'query' ]."</td>" );
  1106.                         echo "\n\t\t<td style = 'border: 1px solid black; padding: 5px;'>".
  1107.                                 $entry 'time' ]."</td>" );
  1108.                        
  1109.                         echo "\n\t</tr>" );
  1110.                 }
  1111.                
  1112.                 echo "\n\t<tr>" );
  1113.                
  1114.                 echo "\n\t\t<td style = 'border: 1px solid black; padding: 5px;'><strong>Total Time</strong></td>" );
  1115.                 echo "\n\t\t<td style = 'border: 1px solid black; padding: 5px;'>".
  1116.                         $this -> getTotalTime ()."</td>" );
  1117.                
  1118.                 echo "\n\t</tr>" );
  1119.                
  1120.                 echo "\n</table>" );
  1121.         }
  1122. }
  1123. ?>

Documentation generated on Thu, 01 Jul 2010 20:37:17 -0400 by phpDocumentor 1.4.3