2
0

Mysqli.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  7. * This source file is subject to the new BSD license that is bundled
  8. * with this package in the file LICENSE.txt.
  9. * It is also available through the world-wide-web at this URL:
  10. * http://framework.zend.com/license/new-bsd
  11. * If you did not receive a copy of the license and are unable to
  12. * obtain it through the world-wide-web, please send an email
  13. * to license@zend.com so we can send you a copy immediately.
  14. *
  15. * @category Zend
  16. * @package Zend_Db
  17. * @subpackage Statement
  18. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id$
  21. */
  22. /**
  23. * @see Zend_Db_Statement
  24. */
  25. require_once 'Zend/Db/Statement.php';
  26. /**
  27. * Extends for Mysqli
  28. *
  29. * @category Zend
  30. * @package Zend_Db
  31. * @subpackage Statement
  32. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. class Zend_Db_Statement_Mysqli extends Zend_Db_Statement
  36. {
  37. /**
  38. * The mysqli_stmt object.
  39. *
  40. * @var mysqli_stmt
  41. */
  42. protected $_stmt;
  43. /**
  44. * Column names.
  45. *
  46. * @var array
  47. */
  48. protected $_keys;
  49. /**
  50. * Fetched result values.
  51. *
  52. * @var array
  53. */
  54. protected $_values;
  55. /**
  56. * @var array
  57. */
  58. protected $_meta = null;
  59. /**
  60. * @param string $sql
  61. * @return void
  62. * @throws Zend_Db_Statement_Mysqli_Exception
  63. */
  64. public function _prepare($sql)
  65. {
  66. $mysqli = $this->_adapter->getConnection();
  67. $this->_stmt = $mysqli->prepare($sql);
  68. if ($this->_stmt === false || $mysqli->errno) {
  69. /**
  70. * @see Zend_Db_Statement_Mysqli_Exception
  71. */
  72. require_once 'Zend/Db/Statement/Mysqli/Exception.php';
  73. throw new Zend_Db_Statement_Mysqli_Exception("Mysqli prepare error: " . $mysqli->error);
  74. }
  75. }
  76. /**
  77. * Binds a parameter to the specified variable name.
  78. *
  79. * @param mixed $parameter Name the parameter, either integer or string.
  80. * @param mixed $variable Reference to PHP variable containing the value.
  81. * @param mixed $type OPTIONAL Datatype of SQL parameter.
  82. * @param mixed $length OPTIONAL Length of SQL parameter.
  83. * @param mixed $options OPTIONAL Other options.
  84. * @return bool
  85. * @throws Zend_Db_Statement_Mysqli_Exception
  86. */
  87. protected function _bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
  88. {
  89. return true;
  90. }
  91. /**
  92. * Closes the cursor and the statement.
  93. *
  94. * @return bool
  95. */
  96. public function close()
  97. {
  98. if ($this->_stmt) {
  99. $r = $this->_stmt->close();
  100. $this->_stmt = null;
  101. return $r;
  102. }
  103. return false;
  104. }
  105. /**
  106. * Closes the cursor, allowing the statement to be executed again.
  107. *
  108. * @return bool
  109. */
  110. public function closeCursor()
  111. {
  112. if ($stmt = $this->_stmt) {
  113. $mysqli = $this->_adapter->getConnection();
  114. while ($mysqli->next_result()) {}
  115. $this->_stmt->free_result();
  116. return $this->_stmt->reset();
  117. }
  118. return false;
  119. }
  120. /**
  121. * Returns the number of columns in the result set.
  122. * Returns null if the statement has no result set metadata.
  123. *
  124. * @return int The number of columns.
  125. */
  126. public function columnCount()
  127. {
  128. if (isset($this->_meta) && $this->_meta) {
  129. return $this->_meta->field_count;
  130. }
  131. return 0;
  132. }
  133. /**
  134. * Retrieves the error code, if any, associated with the last operation on
  135. * the statement handle.
  136. *
  137. * @return string error code.
  138. */
  139. public function errorCode()
  140. {
  141. if (!$this->_stmt) {
  142. return false;
  143. }
  144. return substr($this->_stmt->sqlstate, 0, 5);
  145. }
  146. /**
  147. * Retrieves an array of error information, if any, associated with the
  148. * last operation on the statement handle.
  149. *
  150. * @return array
  151. */
  152. public function errorInfo()
  153. {
  154. if (!$this->_stmt) {
  155. return false;
  156. }
  157. return array(
  158. substr($this->_stmt->sqlstate, 0, 5),
  159. $this->_stmt->errno,
  160. $this->_stmt->error,
  161. );
  162. }
  163. /**
  164. * Executes a prepared statement.
  165. *
  166. * @param array $params OPTIONAL Values to bind to parameter placeholders.
  167. * @return bool
  168. * @throws Zend_Db_Statement_Mysqli_Exception
  169. */
  170. public function _execute(array $params = null)
  171. {
  172. if (!$this->_stmt) {
  173. return false;
  174. }
  175. // if no params were given as an argument to execute(),
  176. // then default to the _bindParam array
  177. if ($params === null) {
  178. $params = $this->_bindParam;
  179. }
  180. // send $params as input parameters to the statement
  181. if ($params) {
  182. array_unshift($params, str_repeat('s', count($params)));
  183. call_user_func_array(
  184. array($this->_stmt, 'bind_param'),
  185. $params
  186. );
  187. }
  188. // execute the statement
  189. $retval = $this->_stmt->execute();
  190. if ($retval === false) {
  191. /**
  192. * @see Zend_Db_Statement_Mysqli_Exception
  193. */
  194. require_once 'Zend/Db/Statement/Mysqli/Exception.php';
  195. throw new Zend_Db_Statement_Mysqli_Exception("Mysqli statement execute error : " . $this->_stmt->error);
  196. }
  197. // retain metadata
  198. if ($this->_meta === null) {
  199. $this->_meta = $this->_stmt->result_metadata();
  200. if ($this->_stmt->errno) {
  201. /**
  202. * @see Zend_Db_Statement_Mysqli_Exception
  203. */
  204. require_once 'Zend/Db/Statement/Mysqli/Exception.php';
  205. throw new Zend_Db_Statement_Mysqli_Exception("Mysqli statement metadata error: " . $this->_stmt->error);
  206. }
  207. }
  208. // statements that have no result set do not return metadata
  209. if ($this->_meta !== false) {
  210. // get the column names that will result
  211. $this->_keys = array();
  212. foreach ($this->_meta->fetch_fields() as $col) {
  213. $this->_keys[] = $this->_adapter->foldCase($col->name);
  214. }
  215. // set up a binding space for result variables
  216. $this->_values = array_fill(0, count($this->_keys), null);
  217. // set up references to the result binding space.
  218. // just passing $this->_values in the call_user_func_array()
  219. // below won't work, you need references.
  220. $refs = array();
  221. foreach ($this->_values as $i => &$f) {
  222. $refs[$i] = &$f;
  223. }
  224. $this->_stmt->store_result();
  225. // bind to the result variables
  226. call_user_func_array(
  227. array($this->_stmt, 'bind_result'),
  228. $this->_values
  229. );
  230. }
  231. return $retval;
  232. }
  233. /**
  234. * Fetches a row from the result set.
  235. *
  236. * @param int $style OPTIONAL Fetch mode for this fetch operation.
  237. * @param int $cursor OPTIONAL Absolute, relative, or other.
  238. * @param int $offset OPTIONAL Number for absolute or relative cursors.
  239. * @return mixed Array, object, or scalar depending on fetch mode.
  240. * @throws Zend_Db_Statement_Mysqli_Exception
  241. */
  242. public function fetch($style = null, $cursor = null, $offset = null)
  243. {
  244. if (!$this->_stmt) {
  245. return false;
  246. }
  247. // fetch the next result
  248. $retval = $this->_stmt->fetch();
  249. switch ($retval) {
  250. case null: // end of data
  251. case false: // error occurred
  252. $this->_stmt->reset();
  253. return $retval;
  254. default:
  255. // fallthrough
  256. }
  257. // make sure we have a fetch mode
  258. if ($style === null) {
  259. $style = $this->_fetchMode;
  260. }
  261. // dereference the result values, otherwise things like fetchAll()
  262. // return the same values for every entry (because of the reference).
  263. $values = array();
  264. foreach ($this->_values as $key => $val) {
  265. $values[] = $val;
  266. }
  267. $row = false;
  268. switch ($style) {
  269. case Zend_Db::FETCH_NUM:
  270. $row = $values;
  271. break;
  272. case Zend_Db::FETCH_ASSOC:
  273. $row = array_combine($this->_keys, $values);
  274. break;
  275. case Zend_Db::FETCH_BOTH:
  276. $assoc = array_combine($this->_keys, $values);
  277. $row = array_merge($values, $assoc);
  278. break;
  279. case Zend_Db::FETCH_OBJ:
  280. $row = (object) array_combine($this->_keys, $values);
  281. break;
  282. case Zend_Db::FETCH_BOUND:
  283. $assoc = array_combine($this->_keys, $values);
  284. $row = array_merge($values, $assoc);
  285. return $this->_fetchBound($row);
  286. break;
  287. default:
  288. /**
  289. * @see Zend_Db_Statement_Mysqli_Exception
  290. */
  291. require_once 'Zend/Db/Statement/Mysqli/Exception.php';
  292. throw new Zend_Db_Statement_Mysqli_Exception("Invalid fetch mode '$style' specified");
  293. break;
  294. }
  295. return $row;
  296. }
  297. /**
  298. * Retrieves the next rowset (result set) for a SQL statement that has
  299. * multiple result sets. An example is a stored procedure that returns
  300. * the results of multiple queries.
  301. *
  302. * @return bool
  303. * @throws Zend_Db_Statement_Mysqli_Exception
  304. */
  305. public function nextRowset()
  306. {
  307. /**
  308. * @see Zend_Db_Statement_Mysqli_Exception
  309. */
  310. require_once 'Zend/Db/Statement/Mysqli/Exception.php';
  311. throw new Zend_Db_Statement_Mysqli_Exception(__FUNCTION__.'() is not implemented');
  312. }
  313. /**
  314. * Returns the number of rows affected by the execution of the
  315. * last INSERT, DELETE, or UPDATE statement executed by this
  316. * statement object.
  317. *
  318. * @return int The number of rows affected.
  319. */
  320. public function rowCount()
  321. {
  322. if (!$this->_adapter) {
  323. return false;
  324. }
  325. $mysqli = $this->_adapter->getConnection();
  326. return $mysqli->affected_rows;
  327. }
  328. }