PageRenderTime 42ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/library/Zend/Db/Adapter/Driver/Mysqli/Result.php

https://github.com/MontmereLimited/zf2
PHP | 299 lines | 138 code | 28 blank | 133 comment | 22 complexity | 2a6ca5c7a1254142058cbfa249cd8548 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 Adapter
  18. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. */
  21. namespace Zend\Db\Adapter\Driver\Mysqli;
  22. use Zend\Db\Adapter\Driver\ResultInterface;
  23. /**
  24. * @category Zend
  25. * @package Zend_Db
  26. * @subpackage Adapter
  27. * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com)
  28. * @license http://framework.zend.com/license/new-bsd New BSD License
  29. */
  30. class Result implements \Iterator, ResultInterface
  31. {
  32. const MODE_STATEMENT = 'statement';
  33. const MODE_RESULT = 'result';
  34. /**
  35. * Mode
  36. *
  37. * @var string
  38. */
  39. protected $mode = null;
  40. /**
  41. * Is query result
  42. *
  43. * @var boolean
  44. */
  45. protected $isQueryResult = true;
  46. /**
  47. * @var \mysqli_result|\mysqli_stmt
  48. */
  49. protected $resource = null;
  50. /**
  51. * Cursor position
  52. * @var int
  53. */
  54. protected $position = 0;
  55. /**
  56. * Number of known rows
  57. * @var int
  58. */
  59. protected $numberOfRows = -1;
  60. /**
  61. * Is the current() operation already complete for this pointer position?
  62. * @var bool
  63. */
  64. protected $currentComplete = false;
  65. /**
  66. *
  67. * @var bool
  68. */
  69. protected $nextComplete = false;
  70. /**
  71. *
  72. * @var bool
  73. */
  74. protected $currentData = false;
  75. /**
  76. *
  77. * @var array
  78. */
  79. protected $statementBindValues = array('keys' => null, 'values' => array());
  80. /**
  81. * Initialize
  82. *
  83. * @param mixed $resource
  84. * @return Result
  85. */
  86. public function initialize($resource)
  87. {
  88. if (!$resource instanceof \mysqli && !$resource instanceof \mysqli_result && !$resource instanceof \mysqli_stmt) {
  89. throw new \InvalidArgumentException('Invalid resource provided.');
  90. }
  91. $this->isQueryResult = (!$resource instanceof \mysqli);
  92. $this->resource = $resource;
  93. $this->mode = ($this->resource instanceof \mysqli_stmt) ? self::MODE_STATEMENT : self::MODE_RESULT;
  94. return $this;
  95. }
  96. /**
  97. *
  98. * @return mixed
  99. */
  100. public function getResource()
  101. {
  102. return $this->resource;
  103. }
  104. /**
  105. * Set is query result
  106. *
  107. * @param boolean $isQueryResult
  108. */
  109. public function setIsQueryResult($isQueryResult)
  110. {
  111. $this->isQueryResult = $isQueryResult;
  112. }
  113. /**
  114. * Is query result
  115. *
  116. * @return boolean
  117. */
  118. public function isQueryResult()
  119. {
  120. return $this->isQueryResult;
  121. }
  122. /**
  123. * Get affected rows
  124. *
  125. * @return integer
  126. */
  127. public function getAffectedRows()
  128. {
  129. if ($this->resource instanceof \mysqli || $this->resource instanceof \mysqli_stmt) {
  130. return $this->resource->affected_rows;
  131. } else {
  132. return $this->resource->num_rows;
  133. }
  134. }
  135. /**
  136. * Current
  137. *
  138. * @return mixed
  139. */
  140. public function current()
  141. {
  142. if ($this->currentComplete) {
  143. return $this->currentData;
  144. }
  145. if ($this->mode == self::MODE_STATEMENT) {
  146. $this->loadDataFromMysqliStatement();
  147. return $this->currentData;
  148. } else {
  149. $this->loadFromMysqliResult();
  150. return $this->currentData;
  151. }
  152. }
  153. /**
  154. * Mysqli's binding and returning of statement values
  155. *
  156. * Mysqli requires you to bind variables to the extension in order to
  157. * get data out. These values have to be references:
  158. * @see http://php.net/manual/en/mysqli-stmt.bind-result.php
  159. *
  160. * @throws \RuntimeException
  161. * @return bool
  162. */
  163. protected function loadDataFromMysqliStatement()
  164. {
  165. $data = null;
  166. // build the default reference based bind strutcure, if it does not already exist
  167. if ($this->statementBindValues['keys'] === null) {
  168. $this->statementBindValues['keys'] = array();
  169. $resultResource = $this->resource->result_metadata();
  170. foreach ($resultResource->fetch_fields() as $col) {
  171. $this->statementBindValues['keys'][] = $col->name;
  172. }
  173. $this->statementBindValues['values'] = array_fill(0, count($this->statementBindValues['keys']), null);
  174. $refs = array();
  175. foreach ($this->statementBindValues['values'] as $i => &$f) {
  176. $refs[$i] = &$f;
  177. }
  178. call_user_func_array(array($this->resource, 'bind_result'), $this->statementBindValues['values']);
  179. }
  180. if (($r = $this->resource->fetch()) === null) {
  181. return false;
  182. } elseif ($r === false) {
  183. throw new \RuntimeException($this->resource->error);
  184. }
  185. // dereference
  186. for ($i = 0; $i < count($this->statementBindValues['keys']); $i++) {
  187. $this->currentData[$this->statementBindValues['keys'][$i]] = $this->statementBindValues['values'][$i];
  188. }
  189. $this->currentComplete = true;
  190. $this->nextComplete = true;
  191. $this->position++;
  192. return true;
  193. }
  194. /**
  195. * Load from mysqli result
  196. *
  197. * @return boolean
  198. */
  199. protected function loadFromMysqliResult()
  200. {
  201. $this->currentData = null;
  202. if (($data = $this->resource->fetch_assoc()) === null) {
  203. return false;
  204. }
  205. $this->position++;
  206. $this->currentData = $data;
  207. $this->currentComplete = true;
  208. $this->nextComplete = true;
  209. $this->position++;
  210. return true;
  211. }
  212. /**
  213. * Next
  214. */
  215. public function next()
  216. {
  217. $this->currentComplete = false;
  218. if ($this->nextComplete == false) {
  219. $this->position++;
  220. }
  221. $this->nextComplete = false;
  222. }
  223. /**
  224. * Key
  225. *
  226. * @return mixed
  227. */
  228. public function key()
  229. {
  230. return $this->position;
  231. }
  232. /**
  233. * Rewind
  234. *
  235. */
  236. public function rewind()
  237. {
  238. $this->currentComplete = false;
  239. $this->position = 0;
  240. if ($this->resource instanceof \mysqli_stmt) {
  241. //$this->resource->reset();
  242. } else {
  243. $this->resource->data_seek(0); // works for both mysqli_result & mysqli_stmt
  244. }
  245. }
  246. /**
  247. * Valid
  248. *
  249. * @return boolean
  250. */
  251. public function valid()
  252. {
  253. if ($this->currentComplete) {
  254. return true;
  255. }
  256. if ($this->mode == self::MODE_STATEMENT) {
  257. return $this->loadDataFromMysqliStatement();
  258. } else {
  259. return $this->loadFromMysqliResult();
  260. }
  261. }
  262. /**
  263. * Count
  264. *
  265. * @return integer
  266. */
  267. public function count()
  268. {
  269. return $this->resource->num_rows;
  270. }
  271. }