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