File indexing completed on 2024-05-26 06:02:52

0001 <?php
0002 /**
0003  * Zend Framework
0004  *
0005  * LICENSE
0006  *
0007  * This source file is subject to the new BSD license that is bundled
0008  * with this package in the file LICENSE.txt.
0009  * It is also available through the world-wide-web at this URL:
0010  * http://framework.zend.com/license/new-bsd
0011  * If you did not receive a copy of the license and are unable to
0012  * obtain it through the world-wide-web, please send an email
0013  * to license@zend.com so we can send you a copy immediately.
0014  *
0015  * @category   Zend
0016  * @package    Zend_Db
0017  * @subpackage Statement
0018  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0019  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0020  * @version    $Id$
0021  */
0022 
0023 
0024 /**
0025  * @see Zend_Db_Statement
0026  */
0027 // require_once 'Zend/Db/Statement.php';
0028 
0029 
0030 /**
0031  * Extends for Mysqli
0032  *
0033  * @category   Zend
0034  * @package    Zend_Db
0035  * @subpackage Statement
0036  * @copyright  Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
0037  * @license    http://framework.zend.com/license/new-bsd     New BSD License
0038  */
0039 class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
0040 {
0041 
0042     /**
0043      * Column names.
0044      *
0045      * @var array
0046      */
0047     protected $_keys;
0048 
0049     /**
0050      * Fetched result values.
0051      *
0052      * @var array
0053      */
0054     protected $_values;
0055 
0056     /**
0057      * @var array
0058      */
0059     protected $_meta = null;
0060 
0061     /**
0062      * @param  string $sql
0063      * @return void
0064      * @throws Zend_Db_Statement_Mysqli_Exception
0065      */
0066     public function _prepare($sql)
0067     {
0068         $mysqli = $this->_adapter->getConnection();
0069 
0070         $this->_stmt = $mysqli->prepare($sql);
0071 
0072         if ($this->_stmt === false || $mysqli->errno) {
0073             /**
0074              * @see Zend_Db_Statement_Mysqli_Exception
0075              */
0076             // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
0077             throw new Zend_Db_Statement_Mysqli_Exception("Mysqli prepare error: " . $mysqli->error, $mysqli->errno);
0078         }
0079     }
0080 
0081     /**
0082      * Binds a parameter to the specified variable name.
0083      *
0084      * @param mixed $parameter Name the parameter, either integer or string.
0085      * @param mixed $variable  Reference to PHP variable containing the value.
0086      * @param mixed $type      OPTIONAL Datatype of SQL parameter.
0087      * @param mixed $length    OPTIONAL Length of SQL parameter.
0088      * @param mixed $options   OPTIONAL Other options.
0089      * @return bool
0090      * @throws Zend_Db_Statement_Mysqli_Exception
0091      */
0092     protected function _bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
0093     {
0094         return true;
0095     }
0096 
0097     /**
0098      * Closes the cursor and the statement.
0099      *
0100      * @return bool
0101      */
0102     public function close()
0103     {
0104         if ($this->_stmt) {
0105             $r = $this->_stmt->close();
0106             $this->_stmt = null;
0107             return $r;
0108         }
0109         return false;
0110     }
0111 
0112     /**
0113      * Closes the cursor, allowing the statement to be executed again.
0114      *
0115      * @return bool
0116      */
0117     public function closeCursor()
0118     {
0119         if ($stmt = $this->_stmt) {
0120             $mysqli = $this->_adapter->getConnection();
0121             while ($mysqli->more_results()) {
0122                 $mysqli->next_result();
0123             }
0124             $this->_stmt->free_result();
0125             return $this->_stmt->reset();
0126         }
0127         return false;
0128     }
0129 
0130     /**
0131      * Returns the number of columns in the result set.
0132      * Returns null if the statement has no result set metadata.
0133      *
0134      * @return int The number of columns.
0135      */
0136     public function columnCount()
0137     {
0138         if (isset($this->_meta) && $this->_meta) {
0139             return $this->_meta->field_count;
0140         }
0141         return 0;
0142     }
0143 
0144     /**
0145      * Retrieves the error code, if any, associated with the last operation on
0146      * the statement handle.
0147      *
0148      * @return string error code.
0149      */
0150     public function errorCode()
0151     {
0152         if (!$this->_stmt) {
0153             return false;
0154         }
0155         return substr($this->_stmt->sqlstate, 0, 5);
0156     }
0157 
0158     /**
0159      * Retrieves an array of error information, if any, associated with the
0160      * last operation on the statement handle.
0161      *
0162      * @return array
0163      */
0164     public function errorInfo()
0165     {
0166         if (!$this->_stmt) {
0167             return false;
0168         }
0169         return array(
0170             substr($this->_stmt->sqlstate, 0, 5),
0171             $this->_stmt->errno,
0172             $this->_stmt->error,
0173         );
0174     }
0175 
0176     /**
0177      * Executes a prepared statement.
0178      *
0179      * @param array $params OPTIONAL Values to bind to parameter placeholders.
0180      * @return bool
0181      * @throws Zend_Db_Statement_Mysqli_Exception
0182      */
0183     public function _execute(array $params = null)
0184     {
0185         if (!$this->_stmt) {
0186             return false;
0187         }
0188 
0189         // if no params were given as an argument to execute(),
0190         // then default to the _bindParam array
0191         if ($params === null) {
0192             $params = $this->_bindParam;
0193         }
0194         // send $params as input parameters to the statement
0195         if ($params) {
0196             array_unshift($params, str_repeat('s', count($params)));
0197             $stmtParams = array();
0198             foreach ($params as $k => &$value) {
0199                 $stmtParams[$k] = &$value;
0200             }
0201             call_user_func_array(
0202                 array($this->_stmt, 'bind_param'),
0203                 $stmtParams
0204                 );
0205         }
0206 
0207         // execute the statement
0208         $retval = $this->_stmt->execute();
0209         if ($retval === false) {
0210             /**
0211              * @see Zend_Db_Statement_Mysqli_Exception
0212              */
0213             // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
0214             throw new Zend_Db_Statement_Mysqli_Exception("Mysqli statement execute error : " . $this->_stmt->error, $this->_stmt->errno);
0215         }
0216 
0217 
0218         // retain metadata
0219         if ($this->_meta === null) {
0220             $this->_meta = $this->_stmt->result_metadata();
0221             if ($this->_stmt->errno) {
0222                 /**
0223                  * @see Zend_Db_Statement_Mysqli_Exception
0224                  */
0225                 // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
0226                 throw new Zend_Db_Statement_Mysqli_Exception("Mysqli statement metadata error: " . $this->_stmt->error, $this->_stmt->errno);
0227             }
0228         }
0229 
0230         // statements that have no result set do not return metadata
0231         if ($this->_meta !== false) {
0232 
0233             // get the column names that will result
0234             $this->_keys = array();
0235             foreach ($this->_meta->fetch_fields() as $col) {
0236                 $this->_keys[] = $this->_adapter->foldCase($col->name);
0237             }
0238 
0239             // set up a binding space for result variables
0240             $this->_values = array_fill(0, count($this->_keys), null);
0241 
0242             // set up references to the result binding space.
0243             // just passing $this->_values in the call_user_func_array()
0244             // below won't work, you need references.
0245             $refs = array();
0246             foreach ($this->_values as $i => &$f) {
0247                 $refs[$i] = &$f;
0248             }
0249 
0250             $this->_stmt->store_result();
0251             // bind to the result variables
0252             call_user_func_array(
0253                 array($this->_stmt, 'bind_result'),
0254                 $this->_values
0255             );
0256         }
0257         return $retval;
0258     }
0259 
0260 
0261     /**
0262      * Fetches a row from the result set.
0263      *
0264      * @param int $style  OPTIONAL Fetch mode for this fetch operation.
0265      * @param int $cursor OPTIONAL Absolute, relative, or other.
0266      * @param int $offset OPTIONAL Number for absolute or relative cursors.
0267      * @return mixed Array, object, or scalar depending on fetch mode.
0268      * @throws Zend_Db_Statement_Mysqli_Exception
0269      */
0270     public function fetch($style = null, $cursor = null, $offset = null)
0271     {
0272         if (!$this->_stmt) {
0273             return false;
0274         }
0275         // fetch the next result
0276         $retval = $this->_stmt->fetch();
0277         switch ($retval) {
0278             case null: // end of data
0279             case false: // error occurred
0280                 $this->_stmt->reset();
0281                 return false;
0282             default:
0283                 // fallthrough
0284         }
0285 
0286         // make sure we have a fetch mode
0287         if ($style === null) {
0288             $style = $this->_fetchMode;
0289         }
0290 
0291         // dereference the result values, otherwise things like fetchAll()
0292         // return the same values for every entry (because of the reference).
0293         $values = array();
0294         foreach ($this->_values as $key => $val) {
0295             $values[] = $val;
0296         }
0297 
0298         $row = false;
0299         switch ($style) {
0300             case Zend_Db::FETCH_NUM:
0301                 $row = $values;
0302                 break;
0303             case Zend_Db::FETCH_ASSOC:
0304                 $row = array_combine($this->_keys, $values);
0305                 break;
0306             case Zend_Db::FETCH_BOTH:
0307                 $assoc = array_combine($this->_keys, $values);
0308                 $row = array_merge($values, $assoc);
0309                 break;
0310             case Zend_Db::FETCH_OBJ:
0311                 $row = (object) array_combine($this->_keys, $values);
0312                 break;
0313             case Zend_Db::FETCH_BOUND:
0314                 $assoc = array_combine($this->_keys, $values);
0315                 $row = array_merge($values, $assoc);
0316                 return $this->_fetchBound($row);
0317                 break;
0318             default:
0319                 /**
0320                  * @see Zend_Db_Statement_Mysqli_Exception
0321                  */
0322                 // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
0323                 throw new Zend_Db_Statement_Mysqli_Exception("Invalid fetch mode '$style' specified");
0324                 break;
0325         }
0326         return $row;
0327     }
0328 
0329     /**
0330      * Retrieves the next rowset (result set) for a SQL statement that has
0331      * multiple result sets.  An example is a stored procedure that returns
0332      * the results of multiple queries.
0333      *
0334      * @return bool
0335      * @throws Zend_Db_Statement_Mysqli_Exception
0336      */
0337     public function nextRowset()
0338     {
0339         /**
0340          * @see Zend_Db_Statement_Mysqli_Exception
0341          */
0342         // require_once 'Zend/Db/Statement/Mysqli/Exception.php';
0343         throw new Zend_Db_Statement_Mysqli_Exception(__FUNCTION__.'() is not implemented');
0344     }
0345 
0346     /**
0347      * Returns the number of rows affected by the execution of the
0348      * last INSERT, DELETE, or UPDATE statement executed by this
0349      * statement object.
0350      *
0351      * @return int     The number of rows affected.
0352      */
0353     public function rowCount()
0354     {
0355         if (!$this->_adapter) {
0356             return false;
0357         }
0358         $mysqli = $this->_adapter->getConnection();
0359         return $mysqli->affected_rows;
0360     }
0361 
0362 }