PageRenderTime 52ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Db/Statement/Mysqli.php

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