-
open/home/peruvian/subdomains/m.peruvianvip.com/vendor/zendframework/zendframework1/library/Zend/Db/Statement.php
Zend_Db_Statement_Pdo->_execute(Array(0))
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-2015 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 /**
24 * @see Zend_Db
25 */
26 require_once 'Zend/Db.php';
27
28 /**
29 * @see Zend_Db_Statement_Interface
30 */
31 require_once 'Zend/Db/Statement/Interface.php';
32
33 /**
34 * Abstract class to emulate a PDOStatement for native database adapters.
35 *
36 * @category Zend
37 * @package Zend_Db
38 * @subpackage Statement
39 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
40 * @license http://framework.zend.com/license/new-bsd New BSD License
41 */
42 abstract class Zend_Db_Statement implements Zend_Db_Statement_Interface
43 {
44
45 /**
46 * @var resource|object The driver level statement object/resource
47 */
48 protected $_stmt = null;
49
50 /**
51 * @var Zend_Db_Adapter_Abstract
52 */
53 protected $_adapter = null;
54
55 /**
56 * The current fetch mode.
57 *
58 * @var integer
59 */
60 protected $_fetchMode = Zend_Db::FETCH_ASSOC;
61
62 /**
63 * Attributes.
64 *
65 * @var array
66 */
67 protected $_attribute = array();
68
69 /**
70 * Column result bindings.
71 *
72 * @var array
73 */
74 protected $_bindColumn = array();
75
76 /**
77 * Query parameter bindings; covers bindParam() and bindValue().
78 *
79 * @var array
80 */
81 protected $_bindParam = array();
82
83 /**
84 * SQL string split into an array at placeholders.
85 *
86 * @var array
87 */
88 protected $_sqlSplit = array();
89
90 /**
91 * Parameter placeholders in the SQL string by position in the split array.
92 *
93 * @var array
94 */
95 protected $_sqlParam = array();
96
97 /**
98 * @var Zend_Db_Profiler_Query
99 */
100 protected $_queryId = null;
101
102 /**
103 * Constructor for a statement.
104 *
105 * @param Zend_Db_Adapter_Abstract $adapter
106 * @param mixed $sql Either a string or Zend_Db_Select.
107 */
108 public function __construct($adapter, $sql)
109 {
110 $this->_adapter = $adapter;
111 if ($sql instanceof Zend_Db_Select) {
112 $sql = $sql->assemble();
113 }
114 $this->_parseParameters($sql);
115 $this->_prepare($sql);
116
117 $this->_queryId = $this->_adapter->getProfiler()->queryStart($sql);
118 }
119
120 /**
121 * Internal method called by abstract statment constructor to setup
122 * the driver level statement
123 *
124 * @return void
125 */
126 protected function _prepare($sql)
127 {
128 return;
129 }
130
131 /**
132 * @param string $sql
133 * @return void
134 */
135 protected function _parseParameters($sql)
136 {
137 $sql = $this->_stripQuoted($sql);
138
139 // split into text and params
140 $this->_sqlSplit = preg_split('/(\?|\:[a-zA-Z0-9_]+)/',
141 $sql, -1, PREG_SPLIT_DELIM_CAPTURE|PREG_SPLIT_NO_EMPTY);
142
143 // map params
144 $this->_sqlParam = array();
145 foreach ($this->_sqlSplit as $key => $val) {
146 if ($val == '?') {
147 if ($this->_adapter->supportsParameters('positional') === false) {
148 /**
149 * @see Zend_Db_Statement_Exception
150 */
151 require_once 'Zend/Db/Statement/Exception.php';
152 throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$val'");
153 }
154 } else if ($val[0] == ':') {
155 if ($this->_adapter->supportsParameters('named') === false) {
156 /**
157 * @see Zend_Db_Statement_Exception
158 */
159 require_once 'Zend/Db/Statement/Exception.php';
160 throw new Zend_Db_Statement_Exception("Invalid bind-variable name '$val'");
161 }
162 }
163 $this->_sqlParam[] = $val;
164 }
165
166 // set up for binding
167 $this->_bindParam = array();
168 }
169
170 /**
171 * Remove parts of a SQL string that contain quoted strings
172 * of values or identifiers.
173 *
174 * @param string $sql
175 * @return string
176 */
177 protected function _stripQuoted($sql)
178 {
179
180 // get the character for value quoting
181 // this should be '
182 $q = $this->_adapter->quote('a');
183 $q = $q[0];
184 // get the value used as an escaped quote,
185 // e.g. \' or ''
186 $qe = $this->_adapter->quote($q);
187 $qe = substr($qe, 1, 2);
188 $qe = preg_quote($qe);
189 $escapeChar = substr($qe,0,1);
190 // remove 'foo\'bar'
191 if (!empty($q)) {
192 $escapeChar = preg_quote($escapeChar);
193 // this segfaults only after 65,000 characters instead of 9,000
194 $sql = preg_replace("/$q([^$q{$escapeChar}]*|($qe)*)*$q/s", '', $sql);
195 }
196
197 // get a version of the SQL statement with all quoted
198 // values and delimited identifiers stripped out
199 // remove "foo\"bar"
200 $sql = preg_replace("/\"(\\\\\"|[^\"])*\"/Us", '', $sql);
201
202 // get the character for delimited id quotes,
203 // this is usually " but in MySQL is `
204 $d = $this->_adapter->quoteIdentifier('a');
205 $d = $d[0];
206 // get the value used as an escaped delimited id quote,
207 // e.g. \" or "" or \`
208 $de = $this->_adapter->quoteIdentifier($d);
209 $de = substr($de, 1, 2);
210 $de = preg_quote($de);
211 // Note: $de and $d where never used..., now they are:
212 $sql = preg_replace("/$d($de|\\\\{2}|[^$d])*$d/Us", '', $sql);
213 return $sql;
214 }
215
216 /**
217 * Bind a column of the statement result set to a PHP variable.
218 *
219 * @param string $column Name the column in the result set, either by
220 * position or by name.
221 * @param mixed $param Reference to the PHP variable containing the value.
222 * @param mixed $type OPTIONAL
223 * @return bool
224 */
225 public function bindColumn($column, &$param, $type = null)
226 {
227 $this->_bindColumn[$column] =& $param;
228 return true;
229 }
230
231 /**
232 * Binds a parameter to the specified variable name.
233 *
234 * @param mixed $parameter Name the parameter, either integer or string.
235 * @param mixed $variable Reference to PHP variable containing the value.
236 * @param mixed $type OPTIONAL Datatype of SQL parameter.
237 * @param mixed $length OPTIONAL Length of SQL parameter.
238 * @param mixed $options OPTIONAL Other options.
239 * @return bool
240 */
241 public function bindParam($parameter, &$variable, $type = null, $length = null, $options = null)
242 {
243 if (!is_int($parameter) && !is_string($parameter)) {
244 /**
245 * @see Zend_Db_Statement_Exception
246 */
247 require_once 'Zend/Db/Statement/Exception.php';
248 throw new Zend_Db_Statement_Exception('Invalid bind-variable position');
249 }
250
251 $position = null;
252 if (($intval = (int) $parameter) > 0 && $this->_adapter->supportsParameters('positional')) {
253 if ($intval >= 1 || $intval <= count($this->_sqlParam)) {
254 $position = $intval;
255 }
256 } else if ($this->_adapter->supportsParameters('named')) {
257 if ($parameter[0] != ':') {
258 $parameter = ':' . $parameter;
259 }
260 if (in_array($parameter, $this->_sqlParam) !== false) {
261 $position = $parameter;
262 }
263 }
264
265 if ($position === null) {
266 /**
267 * @see Zend_Db_Statement_Exception
268 */
269 require_once 'Zend/Db/Statement/Exception.php';
270 throw new Zend_Db_Statement_Exception("Invalid bind-variable position '$parameter'");
271 }
272
273 // Finally we are assured that $position is valid
274 $this->_bindParam[$position] =& $variable;
275 return $this->_bindParam($position, $variable, $type, $length, $options);
276 }
277
278 /**
279 * Binds a value to a parameter.
280 *
281 * @param mixed $parameter Name the parameter, either integer or string.
282 * @param mixed $value Scalar value to bind to the parameter.
283 * @param mixed $type OPTIONAL Datatype of the parameter.
284 * @return bool
285 */
286 public function bindValue($parameter, $value, $type = null)
287 {
288 return $this->bindParam($parameter, $value, $type);
289 }
290
291 /**
292 * Executes a prepared statement.
293 *
294 * @param array $params OPTIONAL Values to bind to parameter placeholders.
295 * @return bool
296 */
297 public function execute(array $params = null)
298 {
299 /*
300 * Simple case - no query profiler to manage.
301 */
302 if ($this->_queryId === null) {
303 return $this->_execute($params);
304 }
305
306 /*
307 * Do the same thing, but with query profiler
308 * management before and after the execute.
309 */
310 $prof = $this->_adapter->getProfiler();
311 $qp = $prof->getQueryProfile($this->_queryId);
312 if ($qp->hasEnded()) {
313 $this->_queryId = $prof->queryClone($qp);
314 $qp = $prof->getQueryProfile($this->_queryId);
315 }
316 if ($params !== null) {
317 $qp->bindParams($params);
318 } else {
319 $qp->bindParams($this->_bindParam);
320 }
321 $qp->start($this->_queryId);
322
323 $retval = $this->_execute($params);
324
325 $prof->queryEnd($this->_queryId);
326
327 return $retval;
328 }
329
330 /**
331 * Returns an array containing all of the result set rows.
332 *
333 * @param int $style OPTIONAL Fetch mode.
334 * @param int $col OPTIONAL Column number, if fetch mode is by column.
335 * @return array Collection of rows, each in a format by the fetch mode.
336 */
337 public function fetchAll($style = null, $col = null)
338 {
339 $data = array();
340 if ($style === Zend_Db::FETCH_COLUMN && $col === null) {
341 $col = 0;
342 }
343 if ($col === null) {
344 while ($row = $this->fetch($style)) {
345 $data[] = $row;
346 }
347 } else {
348 while (false !== ($val = $this->fetchColumn($col))) {
349 $data[] = $val;
350 }
351 }
352 return $data;
353 }
354
355 /**
356 * Returns a single column from the next row of a result set.
357 *
358 * @param int $col OPTIONAL Position of the column to fetch.
359 * @return string One value from the next row of result set, or false.
360 */
361 public function fetchColumn($col = 0)
362 {
363 $data = array();
364 $col = (int) $col;
365 $row = $this->fetch(Zend_Db::FETCH_NUM);
366 if (!is_array($row)) {
367 return false;
368 }
369 return $row[$col];
370 }
371
372 /**
373 * Fetches the next row and returns it as an object.
374 *
375 * @param string $class OPTIONAL Name of the class to create.
376 * @param array $config OPTIONAL Constructor arguments for the class.
377 * @return mixed One object instance of the specified class, or false.
378 */
379 public function fetchObject($class = 'stdClass', array $config = array())
380 {
381 $obj = new $class($config);
382 $row = $this->fetch(Zend_Db::FETCH_ASSOC);
383 if (!is_array($row)) {
384 return false;
385 }
386 foreach ($row as $key => $val) {
387 $obj->$key = $val;
388 }
389 return $obj;
390 }
391
392 /**
393 * Retrieve a statement attribute.
394 *
395 * @param string $key Attribute name.
396 * @return mixed Attribute value.
397 */
398 public function getAttribute($key)
399 {
400 if (array_key_exists($key, $this->_attribute)) {
401 return $this->_attribute[$key];
402 }
403 }
404
405 /**
406 * Set a statement attribute.
407 *
408 * @param string $key Attribute name.
409 * @param mixed $val Attribute value.
410 * @return bool
411 */
412 public function setAttribute($key, $val)
413 {
414 $this->_attribute[$key] = $val;
415 }
416
417 /**
418 * Set the default fetch mode for this statement.
419 *
420 * @param int $mode The fetch mode.
421 * @return bool
422 * @throws Zend_Db_Statement_Exception
423 */
424 public function setFetchMode($mode)
425 {
426 switch ($mode) {
427 case Zend_Db::FETCH_NUM:
428 case Zend_Db::FETCH_ASSOC:
429 case Zend_Db::FETCH_BOTH:
430 case Zend_Db::FETCH_OBJ:
431 $this->_fetchMode = $mode;
432 break;
433 case Zend_Db::FETCH_BOUND:
434 default:
435 $this->closeCursor();
436 /**
437 * @see Zend_Db_Statement_Exception
438 */
439 require_once 'Zend/Db/Statement/Exception.php';
440 throw new Zend_Db_Statement_Exception('invalid fetch mode');
441 break;
442 }
443 }
444
445 /**
446 * Helper function to map retrieved row
447 * to bound column variables
448 *
449 * @param array $row
450 * @return bool True
451 */
452 public function _fetchBound($row)
453 {
454 foreach ($row as $key => $value) {
455 // bindColumn() takes 1-based integer positions
456 // but fetch() returns 0-based integer indexes
457 if (is_int($key)) {
458 $key++;
459 }
460 // set results only to variables that were bound previously
461 if (isset($this->_bindColumn[$key])) {
462 $this->_bindColumn[$key] = $value;
463 }
464 }
465 return true;
466 }
467
468 /**
469 * Gets the Zend_Db_Adapter_Abstract for this
470 * particular Zend_Db_Statement object.
471 *
472 * @return Zend_Db_Adapter_Abstract
473 */
474 public function getAdapter()
475 {
476 return $this->_adapter;
477 }
478
479 /**
480 * Gets the resource or object setup by the
481 * _parse
482 * @return unknown_type
483 */
484 public function getDriverStatement()
485 {
486 return $this->_stmt;
487 }
488 }
489
-
open/home/peruvian/subdomains/m.peruvianvip.com/vendor/zendframework/zendframework1/library/Zend/Db/Adapter/Abstract.php
Zend_Db_Statement->execute(Array(0))
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-2015 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
24 /**
25 * @see Zend_Db
26 */
27 require_once 'Zend/Db.php';
28
29 /**
30 * @see Zend_Db_Select
31 */
32 require_once 'Zend/Db/Select.php';
33
34 /**
35 * Class for connecting to SQL databases and performing common operations.
36 *
37 * @category Zend
38 * @package Zend_Db
39 * @subpackage Adapter
40 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
41 * @license http://framework.zend.com/license/new-bsd New BSD License
42 */
43 abstract class Zend_Db_Adapter_Abstract
44 {
45
46 /**
47 * User-provided configuration
48 *
49 * @var array
50 */
51 protected $_config = array();
52
53 /**
54 * Fetch mode
55 *
56 * @var integer
57 */
58 protected $_fetchMode = Zend_Db::FETCH_ASSOC;
59
60 /**
61 * Query profiler object, of type Zend_Db_Profiler
62 * or a subclass of that.
63 *
64 * @var Zend_Db_Profiler
65 */
66 protected $_profiler;
67
68 /**
69 * Default class name for a DB statement.
70 *
71 * @var string
72 */
73 protected $_defaultStmtClass = 'Zend_Db_Statement';
74
75 /**
76 * Default class name for the profiler object.
77 *
78 * @var string
79 */
80 protected $_defaultProfilerClass = 'Zend_Db_Profiler';
81
82 /**
83 * Database connection
84 *
85 * @var object|resource|null
86 */
87 protected $_connection = null;
88
89 /**
90 * Specifies the case of column names retrieved in queries
91 * Options
92 * Zend_Db::CASE_NATURAL (default)
93 * Zend_Db::CASE_LOWER
94 * Zend_Db::CASE_UPPER
95 *
96 * @var integer
97 */
98 protected $_caseFolding = Zend_Db::CASE_NATURAL;
99
100 /**
101 * Specifies whether the adapter automatically quotes identifiers.
102 * If true, most SQL generated by Zend_Db classes applies
103 * identifier quoting automatically.
104 * If false, developer must quote identifiers themselves
105 * by calling quoteIdentifier().
106 *
107 * @var bool
108 */
109 protected $_autoQuoteIdentifiers = true;
110
111 /**
112 * Keys are UPPERCASE SQL datatypes or the constants
113 * Zend_Db::INT_TYPE, Zend_Db::BIGINT_TYPE, or Zend_Db::FLOAT_TYPE.
114 *
115 * Values are:
116 * 0 = 32-bit integer
117 * 1 = 64-bit integer
118 * 2 = float or decimal
119 *
120 * @var array Associative array of datatypes to values 0, 1, or 2.
121 */
122 protected $_numericDataTypes = array(
123 Zend_Db::INT_TYPE => Zend_Db::INT_TYPE,
124 Zend_Db::BIGINT_TYPE => Zend_Db::BIGINT_TYPE,
125 Zend_Db::FLOAT_TYPE => Zend_Db::FLOAT_TYPE
126 );
127
128 /** Weither or not that object can get serialized
129 *
130 * @var bool
131 */
132 protected $_allowSerialization = true;
133
134 /**
135 * Weither or not the database should be reconnected
136 * to that adapter when waking up
137 *
138 * @var bool
139 */
140 protected $_autoReconnectOnUnserialize = false;
141
142 /**
143 * Constructor.
144 *
145 * $config is an array of key/value pairs or an instance of Zend_Config
146 * containing configuration options. These options are common to most adapters:
147 *
148 * dbname => (string) The name of the database to user
149 * username => (string) Connect to the database as this username.
150 * password => (string) Password associated with the username.
151 * host => (string) What host to connect to, defaults to localhost
152 *
153 * Some options are used on a case-by-case basis by adapters:
154 *
155 * port => (string) The port of the database
156 * persistent => (boolean) Whether to use a persistent connection or not, defaults to false
157 * protocol => (string) The network protocol, defaults to TCPIP
158 * caseFolding => (int) style of case-alteration used for identifiers
159 * socket => (string) The socket or named pipe that should be used
160 *
161 * @param array|Zend_Config $config An array or instance of Zend_Config having configuration data
162 * @throws Zend_Db_Adapter_Exception
163 */
164 public function __construct($config)
165 {
166 /*
167 * Verify that adapter parameters are in an array.
168 */
169 if (!is_array($config)) {
170 /*
171 * Convert Zend_Config argument to a plain array.
172 */
173 if ($config instanceof Zend_Config) {
174 $config = $config->toArray();
175 } else {
176 /**
177 * @see Zend_Db_Adapter_Exception
178 */
179 require_once 'Zend/Db/Adapter/Exception.php';
180 throw new Zend_Db_Adapter_Exception('Adapter parameters must be in an array or a Zend_Config object');
181 }
182 }
183
184 $this->_checkRequiredOptions($config);
185
186 $options = array(
187 Zend_Db::CASE_FOLDING => $this->_caseFolding,
188 Zend_Db::AUTO_QUOTE_IDENTIFIERS => $this->_autoQuoteIdentifiers,
189 Zend_Db::FETCH_MODE => $this->_fetchMode,
190 );
191 $driverOptions = array();
192
193 /*
194 * normalize the config and merge it with the defaults
195 */
196 if (array_key_exists('options', $config)) {
197 // can't use array_merge() because keys might be integers
198 foreach ((array) $config['options'] as $key => $value) {
199 $options[$key] = $value;
200 }
201 }
202 if (array_key_exists('driver_options', $config)) {
203 if (!empty($config['driver_options'])) {
204 // can't use array_merge() because keys might be integers
205 foreach ((array) $config['driver_options'] as $key => $value) {
206 $driverOptions[$key] = $value;
207 }
208 }
209 }
210
211 if (!isset($config['charset'])) {
212 $config['charset'] = null;
213 }
214
215 if (!isset($config['persistent'])) {
216 $config['persistent'] = false;
217 }
218
219 $this->_config = array_merge($this->_config, $config);
220 $this->_config['options'] = $options;
221 $this->_config['driver_options'] = $driverOptions;
222
223
224 // obtain the case setting, if there is one
225 if (array_key_exists(Zend_Db::CASE_FOLDING, $options)) {
226 $case = (int) $options[Zend_Db::CASE_FOLDING];
227 switch ($case) {
228 case Zend_Db::CASE_LOWER:
229 case Zend_Db::CASE_UPPER:
230 case Zend_Db::CASE_NATURAL:
231 $this->_caseFolding = $case;
232 break;
233 default:
234 /** @see Zend_Db_Adapter_Exception */
235 require_once 'Zend/Db/Adapter/Exception.php';
236 throw new Zend_Db_Adapter_Exception('Case must be one of the following constants: '
237 . 'Zend_Db::CASE_NATURAL, Zend_Db::CASE_LOWER, Zend_Db::CASE_UPPER');
238 }
239 }
240
241 if (array_key_exists(Zend_Db::FETCH_MODE, $options)) {
242 if (is_string($options[Zend_Db::FETCH_MODE])) {
243 $constant = 'Zend_Db::FETCH_' . strtoupper($options[Zend_Db::FETCH_MODE]);
244 if(defined($constant)) {
245 $options[Zend_Db::FETCH_MODE] = constant($constant);
246 }
247 }
248 $this->setFetchMode((int) $options[Zend_Db::FETCH_MODE]);
249 }
250
251 // obtain quoting property if there is one
252 if (array_key_exists(Zend_Db::AUTO_QUOTE_IDENTIFIERS, $options)) {
253 $this->_autoQuoteIdentifiers = (bool) $options[Zend_Db::AUTO_QUOTE_IDENTIFIERS];
254 }
255
256 // obtain allow serialization property if there is one
257 if (array_key_exists(Zend_Db::ALLOW_SERIALIZATION, $options)) {
258 $this->_allowSerialization = (bool) $options[Zend_Db::ALLOW_SERIALIZATION];
259 }
260
261 // obtain auto reconnect on unserialize property if there is one
262 if (array_key_exists(Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE, $options)) {
263 $this->_autoReconnectOnUnserialize = (bool) $options[Zend_Db::AUTO_RECONNECT_ON_UNSERIALIZE];
264 }
265
266 // create a profiler object
267 $profiler = false;
268 if (array_key_exists(Zend_Db::PROFILER, $this->_config)) {
269 $profiler = $this->_config[Zend_Db::PROFILER];
270 unset($this->_config[Zend_Db::PROFILER]);
271 }
272 $this->setProfiler($profiler);
273 }
274
275 /**
276 * Check for config options that are mandatory.
277 * Throw exceptions if any are missing.
278 *
279 * @param array $config
280 * @throws Zend_Db_Adapter_Exception
281 */
282 protected function _checkRequiredOptions(array $config)
283 {
284 // we need at least a dbname
285 if (! array_key_exists('dbname', $config)) {
286 /** @see Zend_Db_Adapter_Exception */
287 require_once 'Zend/Db/Adapter/Exception.php';
288 throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'dbname' that names the database instance");
289 }
290
291 if (! array_key_exists('password', $config)) {
292 /**
293 * @see Zend_Db_Adapter_Exception
294 */
295 require_once 'Zend/Db/Adapter/Exception.php';
296 throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'password' for login credentials");
297 }
298
299 if (! array_key_exists('username', $config)) {
300 /**
301 * @see Zend_Db_Adapter_Exception
302 */
303 require_once 'Zend/Db/Adapter/Exception.php';
304 throw new Zend_Db_Adapter_Exception("Configuration array must have a key for 'username' for login credentials");
305 }
306 }
307
308 /**
309 * Returns the underlying database connection object or resource.
310 * If not presently connected, this initiates the connection.
311 *
312 * @return object|resource|null
313 */
314 public function getConnection()
315 {
316 $this->_connect();
317 return $this->_connection;
318 }
319
320 /**
321 * Returns the configuration variables in this adapter.
322 *
323 * @return array
324 */
325 public function getConfig()
326 {
327 return $this->_config;
328 }
329
330 /**
331 * Set the adapter's profiler object.
332 *
333 * The argument may be a boolean, an associative array, an instance of
334 * Zend_Db_Profiler, or an instance of Zend_Config.
335 *
336 * A boolean argument sets the profiler to enabled if true, or disabled if
337 * false. The profiler class is the adapter's default profiler class,
338 * Zend_Db_Profiler.
339 *
340 * An instance of Zend_Db_Profiler sets the adapter's instance to that
341 * object. The profiler is enabled and disabled separately.
342 *
343 * An associative array argument may contain any of the keys 'enabled',
344 * 'class', and 'instance'. The 'enabled' and 'instance' keys correspond to the
345 * boolean and object types documented above. The 'class' key is used to name a
346 * class to use for a custom profiler. The class must be Zend_Db_Profiler or a
347 * subclass. The class is instantiated with no constructor arguments. The 'class'
348 * option is ignored when the 'instance' option is supplied.
349 *
350 * An object of type Zend_Config may contain the properties 'enabled', 'class', and
351 * 'instance', just as if an associative array had been passed instead.
352 *
353 * @param Zend_Db_Profiler|Zend_Config|array|boolean $profiler
354 * @return Zend_Db_Adapter_Abstract Provides a fluent interface
355 * @throws Zend_Db_Profiler_Exception if the object instance or class specified
356 * is not Zend_Db_Profiler or an extension of that class.
357 */
358 public function setProfiler($profiler)
359 {
360 $enabled = null;
361 $profilerClass = $this->_defaultProfilerClass;
362 $profilerInstance = null;
363
364 if ($profilerIsObject = is_object($profiler)) {
365 if ($profiler instanceof Zend_Db_Profiler) {
366 $profilerInstance = $profiler;
367 } else if ($profiler instanceof Zend_Config) {
368 $profiler = $profiler->toArray();
369 } else {
370 /**
371 * @see Zend_Db_Profiler_Exception
372 */
373 require_once 'Zend/Db/Profiler/Exception.php';
374 throw new Zend_Db_Profiler_Exception('Profiler argument must be an instance of either Zend_Db_Profiler'
375 . ' or Zend_Config when provided as an object');
376 }
377 }
378
379 if (is_array($profiler)) {
380 if (isset($profiler['enabled'])) {
381 $enabled = (bool) $profiler['enabled'];
382 }
383 if (isset($profiler['class'])) {
384 $profilerClass = $profiler['class'];
385 }
386 if (isset($profiler['instance'])) {
387 $profilerInstance = $profiler['instance'];
388 }
389 } else if (!$profilerIsObject) {
390 $enabled = (bool) $profiler;
391 }
392
393 if ($profilerInstance === null) {
394 if (!class_exists($profilerClass)) {
395 require_once 'Zend/Loader.php';
396 Zend_Loader::loadClass($profilerClass);
397 }
398 $profilerInstance = new $profilerClass();
399 }
400
401 if (!$profilerInstance instanceof Zend_Db_Profiler) {
402 /** @see Zend_Db_Profiler_Exception */
403 require_once 'Zend/Db/Profiler/Exception.php';
404 throw new Zend_Db_Profiler_Exception('Class ' . get_class($profilerInstance) . ' does not extend '
405 . 'Zend_Db_Profiler');
406 }
407
408 if (null !== $enabled) {
409 $profilerInstance->setEnabled($enabled);
410 }
411
412 $this->_profiler = $profilerInstance;
413
414 return $this;
415 }
416
417
418 /**
419 * Returns the profiler for this adapter.
420 *
421 * @return Zend_Db_Profiler
422 */
423 public function getProfiler()
424 {
425 return $this->_profiler;
426 }
427
428 /**
429 * Get the default statement class.
430 *
431 * @return string
432 */
433 public function getStatementClass()
434 {
435 return $this->_defaultStmtClass;
436 }
437
438 /**
439 * Set the default statement class.
440 *
441 * @return Zend_Db_Adapter_Abstract Fluent interface
442 */
443 public function setStatementClass($class)
444 {
445 $this->_defaultStmtClass = $class;
446 return $this;
447 }
448
449 /**
450 * Prepares and executes an SQL statement with bound data.
451 *
452 * @param mixed $sql The SQL statement with placeholders.
453 * May be a string or Zend_Db_Select.
454 * @param mixed $bind An array of data to bind to the placeholders.
455 * @return Zend_Db_Statement_Interface
456 */
457 public function query($sql, $bind = array())
458 {
459 // connect to the database if needed
460 $this->_connect();
461
462 // is the $sql a Zend_Db_Select object?
463 if ($sql instanceof Zend_Db_Select) {
464 if (empty($bind)) {
465 $bind = $sql->getBind();
466 }
467
468 $sql = $sql->assemble();
469 }
470
471 // make sure $bind to an array;
472 // don't use (array) typecasting because
473 // because $bind may be a Zend_Db_Expr object
474 if (!is_array($bind)) {
475 $bind = array($bind);
476 }
477
478 // prepare and execute the statement with profiling
479 $stmt = $this->prepare($sql);
480 $stmt->execute($bind);
481
482 // return the results embedded in the prepared statement object
483 $stmt->setFetchMode($this->_fetchMode);
484 return $stmt;
485 }
486
487 /**
488 * Leave autocommit mode and begin a transaction.
489 *
490 * @return Zend_Db_Adapter_Abstract
491 */
492 public function beginTransaction()
493 {
494 $this->_connect();
495 $q = $this->_profiler->queryStart('begin', Zend_Db_Profiler::TRANSACTION);
496 $this->_beginTransaction();
497 $this->_profiler->queryEnd($q);
498 return $this;
499 }
500
501 /**
502 * Commit a transaction and return to autocommit mode.
503 *
504 * @return Zend_Db_Adapter_Abstract
505 */
506 public function commit()
507 {
508 $this->_connect();
509 $q = $this->_profiler->queryStart('commit', Zend_Db_Profiler::TRANSACTION);
510 $this->_commit();
511 $this->_profiler->queryEnd($q);
512 return $this;
513 }
514
515 /**
516 * Roll back a transaction and return to autocommit mode.
517 *
518 * @return Zend_Db_Adapter_Abstract
519 */
520 public function rollBack()
521 {
522 $this->_connect();
523 $q = $this->_profiler->queryStart('rollback', Zend_Db_Profiler::TRANSACTION);
524 $this->_rollBack();
525 $this->_profiler->queryEnd($q);
526 return $this;
527 }
528
529 /**
530 * Inserts a table row with specified data.
531 *
532 * @param mixed $table The table to insert data into.
533 * @param array $bind Column-value pairs.
534 * @return int The number of affected rows.
535 * @throws Zend_Db_Adapter_Exception
536 */
537 public function insert($table, array $bind)
538 {
539 // extract and quote col names from the array keys
540 $cols = array();
541 $vals = array();
542 $i = 0;
543 foreach ($bind as $col => $val) {
544 $cols[] = $this->quoteIdentifier($col, true);
545 if ($val instanceof Zend_Db_Expr) {
546 $vals[] = $val->__toString();
547 unset($bind[$col]);
548 } else {
549 if ($this->supportsParameters('positional')) {
550 $vals[] = '?';
551 } else {
552 if ($this->supportsParameters('named')) {
553 unset($bind[$col]);
554 $bind[':col'.$i] = $val;
555 $vals[] = ':col'.$i;
556 $i++;
557 } else {
558 /** @see Zend_Db_Adapter_Exception */
559 require_once 'Zend/Db/Adapter/Exception.php';
560 throw new Zend_Db_Adapter_Exception(get_class($this) ." doesn't support positional or named binding");
561 }
562 }
563 }
564 }
565
566 // build the statement
567 $sql = "INSERT INTO "
568 . $this->quoteIdentifier($table, true)
569 . ' (' . implode(', ', $cols) . ') '
570 . 'VALUES (' . implode(', ', $vals) . ')';
571
572 // execute the statement and return the number of affected rows
573 if ($this->supportsParameters('positional')) {
574 $bind = array_values($bind);
575 }
576 $stmt = $this->query($sql, $bind);
577 $result = $stmt->rowCount();
578 return $result;
579 }
580
581 /**
582 * Updates table rows with specified data based on a WHERE clause.
583 *
584 * @param mixed $table The table to update.
585 * @param array $bind Column-value pairs.
586 * @param mixed $where UPDATE WHERE clause(s).
587 * @return int The number of affected rows.
588 * @throws Zend_Db_Adapter_Exception
589 */
590 public function update($table, array $bind, $where = '')
591 {
592 /**
593 * Build "col = ?" pairs for the statement,
594 * except for Zend_Db_Expr which is treated literally.
595 */
596 $set = array();
597 $i = 0;
598 foreach ($bind as $col => $val) {
599 if ($val instanceof Zend_Db_Expr) {
600 $val = $val->__toString();
601 unset($bind[$col]);
602 } else {
603 if ($this->supportsParameters('positional')) {
604 $val = '?';
605 } else {
606 if ($this->supportsParameters('named')) {
607 unset($bind[$col]);
608 $bind[':col'.$i] = $val;
609 $val = ':col'.$i;
610 $i++;
611 } else {
612 /** @see Zend_Db_Adapter_Exception */
613 require_once 'Zend/Db/Adapter/Exception.php';
614 throw new Zend_Db_Adapter_Exception(get_class($this) ." doesn't support positional or named binding");
615 }
616 }
617 }
618 $set[] = $this->quoteIdentifier($col, true) . ' = ' . $val;
619 }
620
621 $where = $this->_whereExpr($where);
622
623 /**
624 * Build the UPDATE statement
625 */
626 $sql = "UPDATE "
627 . $this->quoteIdentifier($table, true)
628 . ' SET ' . implode(', ', $set)
629 . (($where) ? " WHERE $where" : '');
630
631 /**
632 * Execute the statement and return the number of affected rows
633 */
634 if ($this->supportsParameters('positional')) {
635 $stmt = $this->query($sql, array_values($bind));
636 } else {
637 $stmt = $this->query($sql, $bind);
638 }
639 $result = $stmt->rowCount();
640 return $result;
641 }
642
643 /**
644 * Deletes table rows based on a WHERE clause.
645 *
646 * @param mixed $table The table to update.
647 * @param mixed $where DELETE WHERE clause(s).
648 * @return int The number of affected rows.
649 */
650 public function delete($table, $where = '')
651 {
652 $where = $this->_whereExpr($where);
653
654 /**
655 * Build the DELETE statement
656 */
657 $sql = "DELETE FROM "
658 . $this->quoteIdentifier($table, true)
659 . (($where) ? " WHERE $where" : '');
660
661 /**
662 * Execute the statement and return the number of affected rows
663 */
664 $stmt = $this->query($sql);
665 $result = $stmt->rowCount();
666 return $result;
667 }
668
669 /**
670 * Convert an array, string, or Zend_Db_Expr object
671 * into a string to put in a WHERE clause.
672 *
673 * @param mixed $where
674 * @return string
675 */
676 protected function _whereExpr($where)
677 {
678 if (empty($where)) {
679 return $where;
680 }
681 if (!is_array($where)) {
682 $where = array($where);
683 }
684 foreach ($where as $cond => &$term) {
685 // is $cond an int? (i.e. Not a condition)
686 if (is_int($cond)) {
687 // $term is the full condition
688 if ($term instanceof Zend_Db_Expr) {
689 $term = $term->__toString();
690 }
691 } else {
692 // $cond is the condition with placeholder,
693 // and $term is quoted into the condition
694 $term = $this->quoteInto($cond, $term);
695 }
696 $term = '(' . $term . ')';
697 }
698
699 $where = implode(' AND ', $where);
700 return $where;
701 }
702
703 /**
704 * Creates and returns a new Zend_Db_Select object for this adapter.
705 *
706 * @return Zend_Db_Select
707 */
708 public function select()
709 {
710 return new Zend_Db_Select($this);
711 }
712
713 /**
714 * Get the fetch mode.
715 *
716 * @return int
717 */
718 public function getFetchMode()
719 {
720 return $this->_fetchMode;
721 }
722
723 /**
724 * Fetches all SQL result rows as a sequential array.
725 * Uses the current fetchMode for the adapter.
726 *
727 * @param string|Zend_Db_Select $sql An SQL SELECT statement.
728 * @param mixed $bind Data to bind into SELECT placeholders.
729 * @param mixed $fetchMode Override current fetch mode.
730 * @return array
731 */
732 public function fetchAll($sql, $bind = array(), $fetchMode = null)
733 {
734 if ($fetchMode === null) {
735 $fetchMode = $this->_fetchMode;
736 }
737 $stmt = $this->query($sql, $bind);
738 $result = $stmt->fetchAll($fetchMode);
739 return $result;
740 }
741
742 /**
743 * Fetches the first row of the SQL result.
744 * Uses the current fetchMode for the adapter.
745 *
746 * @param string|Zend_Db_Select $sql An SQL SELECT statement.
747 * @param mixed $bind Data to bind into SELECT placeholders.
748 * @param mixed $fetchMode Override current fetch mode.
749 * @return mixed Array, object, or scalar depending on fetch mode.
750 */
751 public function fetchRow($sql, $bind = array(), $fetchMode = null)
752 {
753 if ($fetchMode === null) {
754 $fetchMode = $this->_fetchMode;
755 }
756 $stmt = $this->query($sql, $bind);
757 $result = $stmt->fetch($fetchMode);
758 return $result;
759 }
760
761 /**
762 * Fetches all SQL result rows as an associative array.
763 *
764 * The first column is the key, the entire row array is the
765 * value. You should construct the query to be sure that
766 * the first column contains unique values, or else
767 * rows with duplicate values in the first column will
768 * overwrite previous data.
769 *
770 * @param string|Zend_Db_Select $sql An SQL SELECT statement.
771 * @param mixed $bind Data to bind into SELECT placeholders.
772 * @return array
773 */
774 public function fetchAssoc($sql, $bind = array())
775 {
776 $stmt = $this->query($sql, $bind);
777 $data = array();
778 while ($row = $stmt->fetch(Zend_Db::FETCH_ASSOC)) {
779 $tmp = array_values(array_slice($row, 0, 1));
780 $data[$tmp[0]] = $row;
781 }
782 return $data;
783 }
784
785 /**
786 * Fetches the first column of all SQL result rows as an array.
787 *
788 * @param string|Zend_Db_Select $sql An SQL SELECT statement.
789 * @param mixed $bind Data to bind into SELECT placeholders.
790 * @return array
791 */
792 public function fetchCol($sql, $bind = array())
793 {
794 $stmt = $this->query($sql, $bind);
795 $result = $stmt->fetchAll(Zend_Db::FETCH_COLUMN, 0);
796 return $result;
797 }
798
799 /**
800 * Fetches all SQL result rows as an array of key-value pairs.
801 *
802 * The first column is the key, the second column is the
803 * value.
804 *
805 * @param string|Zend_Db_Select $sql An SQL SELECT statement.
806 * @param mixed $bind Data to bind into SELECT placeholders.
807 * @return array
808 */
809 public function fetchPairs($sql, $bind = array())
810 {
811 $stmt = $this->query($sql, $bind);
812 $data = array();
813 while ($row = $stmt->fetch(Zend_Db::FETCH_NUM)) {
814 $data[$row[0]] = $row[1];
815 }
816 return $data;
817 }
818
819 /**
820 * Fetches the first column of the first row of the SQL result.
821 *
822 * @param string|Zend_Db_Select $sql An SQL SELECT statement.
823 * @param mixed $bind Data to bind into SELECT placeholders.
824 * @return string
825 */
826 public function fetchOne($sql, $bind = array())
827 {
828 $stmt = $this->query($sql, $bind);
829 $result = $stmt->fetchColumn(0);
830 return $result;
831 }
832
833 /**
834 * Quote a raw string.
835 *
836 * @param string $value Raw string
837 * @return string Quoted string
838 */
839 protected function _quote($value)
840 {
841 if (is_int($value)) {
842 return $value;
843 } elseif (is_float($value)) {
844 return sprintf('%F', $value);
845 }
846 return "'" . addcslashes($value, "\000\n\r\\'\"\032") . "'";
847 }
848
849 /**
850 * Safely quotes a value for an SQL statement.
851 *
852 * If an array is passed as the value, the array values are quoted
853 * and then returned as a comma-separated string.
854 *
855 * @param mixed $value The value to quote.
856 * @param mixed $type OPTIONAL the SQL datatype name, or constant, or null.
857 * @return mixed An SQL-safe quoted value (or string of separated values).
858 */
859 public function quote($value, $type = null)
860 {
861 $this->_connect();
862
863 if ($value instanceof Zend_Db_Select) {
864 return '(' . $value->assemble() . ')';
865 }
866
867 if ($value instanceof Zend_Db_Expr) {
868 return $value->__toString();
869 }
870
871 if (is_array($value)) {
872 foreach ($value as &$val) {
873 $val = $this->quote($val, $type);
874 }
875 return implode(', ', $value);
876 }
877
878 if ($type !== null && array_key_exists($type = strtoupper($type), $this->_numericDataTypes)) {
879 $quotedValue = '0';
880 switch ($this->_numericDataTypes[$type]) {
881 case Zend_Db::INT_TYPE: // 32-bit integer
882 $quotedValue = (string) intval($value);
883 break;
884 case Zend_Db::BIGINT_TYPE: // 64-bit integer
885 // ANSI SQL-style hex literals (e.g. x'[\dA-F]+')
886 // are not supported here, because these are string
887 // literals, not numeric literals.
888 if (preg_match('/^(
889 [+-]? # optional sign
890 (?:
891 0[Xx][\da-fA-F]+ # ODBC-style hexadecimal
892 |\d+ # decimal or octal, or MySQL ZEROFILL decimal
893 (?:[eE][+-]?\d+)? # optional exponent on decimals or octals
894 )
895 )/x',
896 (string) $value, $matches)) {
897 $quotedValue = $matches[1];
898 }
899 break;
900 case Zend_Db::FLOAT_TYPE: // float or decimal
901 $quotedValue = sprintf('%F', $value);
902 }
903 return $quotedValue;
904 }
905
906 return $this->_quote($value);
907 }
908
909 /**
910 * Quotes a value and places into a piece of text at a placeholder.
911 *
912 * The placeholder is a question-mark; all placeholders will be replaced
913 * with the quoted value. For example:
914 *
915 * <code>
916 * $text = "WHERE date < ?";
917 * $date = "2005-01-02";
918 * $safe = $sql->quoteInto($text, $date);
919 * // $safe = "WHERE date < '2005-01-02'"
920 * </code>
921 *
922 * @param string $text The text with a placeholder.
923 * @param mixed $value The value to quote.
924 * @param string $type OPTIONAL SQL datatype
925 * @param integer $count OPTIONAL count of placeholders to replace
926 * @return string An SQL-safe quoted value placed into the original text.
927 */
928 public function quoteInto($text, $value, $type = null, $count = null)
929 {
930 if ($count === null) {
931 return str_replace('?', $this->quote($value, $type), $text);
932 } else {
933 return implode($this->quote($value, $type), explode('?', $text, $count + 1));
934 }
935 }
936
937 /**
938 * Quotes an identifier.
939 *
940 * Accepts a string representing a qualified indentifier. For Example:
941 * <code>
942 * $adapter->quoteIdentifier('myschema.mytable')
943 * </code>
944 * Returns: "myschema"."mytable"
945 *
946 * Or, an array of one or more identifiers that may form a qualified identifier:
947 * <code>
948 * $adapter->quoteIdentifier(array('myschema','my.table'))
949 * </code>
950 * Returns: "myschema"."my.table"
951 *
952 * The actual quote character surrounding the identifiers may vary depending on
953 * the adapter.
954 *
955 * @param string|array|Zend_Db_Expr $ident The identifier.
956 * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
957 * @return string The quoted identifier.
958 */
959 public function quoteIdentifier($ident, $auto=false)
960 {
961 return $this->_quoteIdentifierAs($ident, null, $auto);
962 }
963
964 /**
965 * Quote a column identifier and alias.
966 *
967 * @param string|array|Zend_Db_Expr $ident The identifier or expression.
968 * @param string $alias An alias for the column.
969 * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
970 * @return string The quoted identifier and alias.
971 */
972 public function quoteColumnAs($ident, $alias, $auto=false)
973 {
974 return $this->_quoteIdentifierAs($ident, $alias, $auto);
975 }
976
977 /**
978 * Quote a table identifier and alias.
979 *
980 * @param string|array|Zend_Db_Expr $ident The identifier or expression.
981 * @param string $alias An alias for the table.
982 * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
983 * @return string The quoted identifier and alias.
984 */
985 public function quoteTableAs($ident, $alias = null, $auto = false)
986 {
987 return $this->_quoteIdentifierAs($ident, $alias, $auto);
988 }
989
990 /**
991 * Quote an identifier and an optional alias.
992 *
993 * @param string|array|Zend_Db_Expr $ident The identifier or expression.
994 * @param string $alias An optional alias.
995 * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
996 * @param string $as The string to add between the identifier/expression and the alias.
997 * @return string The quoted identifier and alias.
998 */
999 protected function _quoteIdentifierAs($ident, $alias = null, $auto = false, $as = ' AS ')
1000 {
1001 if ($ident instanceof Zend_Db_Expr) {
1002 $quoted = $ident->__toString();
1003 } elseif ($ident instanceof Zend_Db_Select) {
1004 $quoted = '(' . $ident->assemble() . ')';
1005 } else {
1006 if (is_string($ident)) {
1007 $ident = explode('.', $ident);
1008 }
1009 if (is_array($ident)) {
1010 $segments = array();
1011 foreach ($ident as $segment) {
1012 if ($segment instanceof Zend_Db_Expr) {
1013 $segments[] = $segment->__toString();
1014 } else {
1015 $segments[] = $this->_quoteIdentifier($segment, $auto);
1016 }
1017 }
1018 if ($alias !== null && end($ident) == $alias) {
1019 $alias = null;
1020 }
1021 $quoted = implode('.', $segments);
1022 } else {
1023 $quoted = $this->_quoteIdentifier($ident, $auto);
1024 }
1025 }
1026 if ($alias !== null) {
1027 $quoted .= $as . $this->_quoteIdentifier($alias, $auto);
1028 }
1029 return $quoted;
1030 }
1031
1032 /**
1033 * Quote an identifier.
1034 *
1035 * @param string $value The identifier or expression.
1036 * @param boolean $auto If true, heed the AUTO_QUOTE_IDENTIFIERS config option.
1037 * @return string The quoted identifier and alias.
1038 */
1039 protected function _quoteIdentifier($value, $auto=false)
1040 {
1041 if ($auto === false || $this->_autoQuoteIdentifiers === true) {
1042 $q = $this->getQuoteIdentifierSymbol();
1043 return ($q . str_replace("$q", "$q$q", $value) . $q);
1044 }
1045 return $value;
1046 }
1047
1048 /**
1049 * Returns the symbol the adapter uses for delimited identifiers.
1050 *
1051 * @return string
1052 */
1053 public function getQuoteIdentifierSymbol()
1054 {
1055 return '"';
1056 }
1057
1058 /**
1059 * Return the most recent value from the specified sequence in the database.
1060 * This is supported only on RDBMS brands that support sequences
1061 * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
1062 *
1063 * @param string $sequenceName
1064 * @return string
1065 */
1066 public function lastSequenceId($sequenceName)
1067 {
1068 return null;
1069 }
1070
1071 /**
1072 * Generate a new value from the specified sequence in the database, and return it.
1073 * This is supported only on RDBMS brands that support sequences
1074 * (e.g. Oracle, PostgreSQL, DB2). Other RDBMS brands return null.
1075 *
1076 * @param string $sequenceName
1077 * @return string
1078 */
1079 public function nextSequenceId($sequenceName)
1080 {
1081 return null;
1082 }
1083
1084 /**
1085 * Helper method to change the case of the strings used
1086 * when returning result sets in FETCH_ASSOC and FETCH_BOTH
1087 * modes.
1088 *
1089 * This is not intended to be used by application code,
1090 * but the method must be public so the Statement class
1091 * can invoke it.
1092 *
1093 * @param string $key
1094 * @return string
1095 */
1096 public function foldCase($key)
1097 {
1098 switch ($this->_caseFolding) {
1099 case Zend_Db::CASE_LOWER:
1100 $value = strtolower((string) $key);
1101 break;
1102 case Zend_Db::CASE_UPPER:
1103 $value = strtoupper((string) $key);
1104 break;
1105 case Zend_Db::CASE_NATURAL:
1106 default:
1107 $value = (string) $key;
1108 }
1109 return $value;
1110 }
1111
1112 /**
1113 * called when object is getting serialized
1114 * This disconnects the DB object that cant be serialized
1115 *
1116 * @throws Zend_Db_Adapter_Exception
1117 * @return array
1118 */
1119 public function __sleep()
1120 {
1121 if ($this->_allowSerialization == false) {
1122 /** @see Zend_Db_Adapter_Exception */
1123 require_once 'Zend/Db/Adapter/Exception.php';
1124 throw new Zend_Db_Adapter_Exception(
1125 get_class($this) . ' is not allowed to be serialized'
1126 );
1127 }
1128 $this->_connection = null;
1129
1130 return array_keys(
1131 array_diff_key(get_object_vars($this), array('_connection' => null))
1132 );
1133 }
1134
1135 /**
1136 * called when object is getting unserialized
1137 *
1138 * @return void
1139 */
1140 public function __wakeup()
1141 {
1142 if ($this->_autoReconnectOnUnserialize == true) {
1143 $this->getConnection();
1144 }
1145 }
1146
1147 /**
1148 * Abstract Methods
1149 */
1150
1151 /**
1152 * Returns a list of the tables in the database.
1153 *
1154 * @return array
1155 */
1156 abstract public function listTables();
1157
1158 /**
1159 * Returns the column descriptions for a table.
1160 *
1161 * The return value is an associative array keyed by the column name,
1162 * as returned by the RDBMS.
1163 *
1164 * The value of each array element is an associative array
1165 * with the following keys:
1166 *
1167 * SCHEMA_NAME => string; name of database or schema
1168 * TABLE_NAME => string;
1169 * COLUMN_NAME => string; column name
1170 * COLUMN_POSITION => number; ordinal position of column in table
1171 * DATA_TYPE => string; SQL datatype name of column
1172 * DEFAULT => string; default expression of column, null if none
1173 * NULLABLE => boolean; true if column can have nulls
1174 * LENGTH => number; length of CHAR/VARCHAR
1175 * SCALE => number; scale of NUMERIC/DECIMAL
1176 * PRECISION => number; precision of NUMERIC/DECIMAL
1177 * UNSIGNED => boolean; unsigned property of an integer type
1178 * PRIMARY => boolean; true if column is part of the primary key
1179 * PRIMARY_POSITION => integer; position of column in primary key
1180 *
1181 * @param string $tableName
1182 * @param string $schemaName OPTIONAL
1183 * @return array
1184 */
1185 abstract public function describeTable($tableName, $schemaName = null);
1186
1187 /**
1188 * Creates a connection to the database.
1189 *
1190 * @return void
1191 */
1192 abstract protected function _connect();
1193
1194 /**
1195 * Test if a connection is active
1196 *
1197 * @return boolean
1198 */
1199 abstract public function isConnected();
1200
1201 /**
1202 * Force the connection to close.
1203 *
1204 * @return void
1205 */
1206 abstract public function closeConnection();
1207
1208 /**
1209 * Prepare a statement and return a PDOStatement-like object.
1210 *
1211 * @param string|Zend_Db_Select $sql SQL query
1212 * @return Zend_Db_Statement|PDOStatement
1213 */
1214 abstract public function prepare($sql);
1215
1216 /**
1217 * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
1218 *
1219 * As a convention, on RDBMS brands that support sequences
1220 * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
1221 * from the arguments and returns the last id generated by that sequence.
1222 * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
1223 * returns the last value generated for such a column, and the table name
1224 * argument is disregarded.
1225 *
1226 * @param string $tableName OPTIONAL Name of table.
1227 * @param string $primaryKey OPTIONAL Name of primary key column.
1228 * @return string
1229 */
1230 abstract public function lastInsertId($tableName = null, $primaryKey = null);
1231
1232 /**
1233 * Begin a transaction.
1234 */
1235 abstract protected function _beginTransaction();
1236
1237 /**
1238 * Commit a transaction.
1239 */
1240 abstract protected function _commit();
1241
1242 /**
1243 * Roll-back a transaction.
1244 */
1245 abstract protected function _rollBack();
1246
1247 /**
1248 * Set the fetch mode.
1249 *
1250 * @param integer $mode
1251 * @return void
1252 * @throws Zend_Db_Adapter_Exception
1253 */
1254 abstract public function setFetchMode($mode);
1255
1256 /**
1257 * Adds an adapter-specific LIMIT clause to the SELECT statement.
1258 *
1259 * @param mixed $sql
1260 * @param integer $count
1261 * @param integer $offset
1262 * @return string
1263 */
1264 abstract public function limit($sql, $count, $offset = 0);
1265
1266 /**
1267 * Check if the adapter supports real SQL parameters.
1268 *
1269 * @param string $type 'positional' or 'named'
1270 * @return bool
1271 */
1272 abstract public function supportsParameters($type);
1273
1274 /**
1275 * Retrieve server version in PHP style
1276 *
1277 * @return string
1278 */
1279 abstract public function getServerVersion();
1280 }
1281
-
open/home/peruvian/subdomains/m.peruvianvip.com/vendor/zendframework/zendframework1/library/Zend/Db/Adapter/Pdo/Abstract.php
Zend_Db_Adapter_Abstract->query('SELECT `co`.* FROM `comentarios` AS `co` WHERE (co.aprobado=1) AND (co.modelo_id=?) ORDER BY `co`.`fecha` DESC LIMIT 15', Array(0))
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-2015 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
24 /**
25 * @see Zend_Db_Adapter_Abstract
26 */
27 require_once 'Zend/Db/Adapter/Abstract.php';
28
29
30 /**
31 * @see Zend_Db_Statement_Pdo
32 */
33 require_once 'Zend/Db/Statement/Pdo.php';
34
35
36 /**
37 * Class for connecting to SQL databases and performing common operations using PDO.
38 *
39 * @category Zend
40 * @package Zend_Db
41 * @subpackage Adapter
42 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
43 * @license http://framework.zend.com/license/new-bsd New BSD License
44 */
45 abstract class Zend_Db_Adapter_Pdo_Abstract extends Zend_Db_Adapter_Abstract
46 {
47
48 /**
49 * Default class name for a DB statement.
50 *
51 * @var string
52 */
53 protected $_defaultStmtClass = 'Zend_Db_Statement_Pdo';
54
55 /**
56 * Creates a PDO DSN for the adapter from $this->_config settings.
57 *
58 * @return string
59 */
60 protected function _dsn()
61 {
62 // baseline of DSN parts
63 $dsn = $this->_config;
64
65 // don't pass the username, password, charset, persistent and driver_options in the DSN
66 unset($dsn['username']);
67 unset($dsn['password']);
68 unset($dsn['options']);
69 unset($dsn['charset']);
70 unset($dsn['persistent']);
71 unset($dsn['driver_options']);
72
73 // use all remaining parts in the DSN
74 foreach ($dsn as $key => $val) {
75 $dsn[$key] = "$key=$val";
76 }
77
78 return $this->_pdoType . ':' . implode(';', $dsn);
79 }
80
81 /**
82 * Creates a PDO object and connects to the database.
83 *
84 * @return void
85 * @throws Zend_Db_Adapter_Exception
86 */
87 protected function _connect()
88 {
89 // if we already have a PDO object, no need to re-connect.
90 if ($this->_connection) {
91 return;
92 }
93
94 // get the dsn first, because some adapters alter the $_pdoType
95 $dsn = $this->_dsn();
96
97 // check for PDO extension
98 if (!extension_loaded('pdo')) {
99 /**
100 * @see Zend_Db_Adapter_Exception
101 */
102 require_once 'Zend/Db/Adapter/Exception.php';
103 throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
104 }
105
106 // check the PDO driver is available
107 if (!in_array($this->_pdoType, PDO::getAvailableDrivers())) {
108 /**
109 * @see Zend_Db_Adapter_Exception
110 */
111 require_once 'Zend/Db/Adapter/Exception.php';
112 throw new Zend_Db_Adapter_Exception('The ' . $this->_pdoType . ' driver is not currently installed');
113 }
114
115 // create PDO connection
116 $q = $this->_profiler->queryStart('connect', Zend_Db_Profiler::CONNECT);
117
118 // add the persistence flag if we find it in our config array
119 if (isset($this->_config['persistent']) && ($this->_config['persistent'] == true)) {
120 $this->_config['driver_options'][PDO::ATTR_PERSISTENT] = true;
121 }
122
123 try {
124 $this->_connection = new PDO(
125 $dsn,
126 $this->_config['username'],
127 $this->_config['password'],
128 $this->_config['driver_options']
129 );
130
131 $this->_profiler->queryEnd($q);
132
133 // set the PDO connection to perform case-folding on array keys, or not
134 $this->_connection->setAttribute(PDO::ATTR_CASE, $this->_caseFolding);
135
136 // always use exceptions.
137 $this->_connection->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
138
139 } catch (PDOException $e) {
140 /**
141 * @see Zend_Db_Adapter_Exception
142 */
143 require_once 'Zend/Db/Adapter/Exception.php';
144 throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
145 }
146
147 }
148
149 /**
150 * Test if a connection is active
151 *
152 * @return boolean
153 */
154 public function isConnected()
155 {
156 return ((bool) ($this->_connection instanceof PDO));
157 }
158
159 /**
160 * Force the connection to close.
161 *
162 * @return void
163 */
164 public function closeConnection()
165 {
166 $this->_connection = null;
167 }
168
169 /**
170 * Prepares an SQL statement.
171 *
172 * @param string $sql The SQL statement with placeholders.
173 * @param array $bind An array of data to bind to the placeholders.
174 * @return PDOStatement
175 */
176 public function prepare($sql)
177 {
178 $this->_connect();
179 $stmtClass = $this->_defaultStmtClass;
180 if (!class_exists($stmtClass)) {
181 require_once 'Zend/Loader.php';
182 Zend_Loader::loadClass($stmtClass);
183 }
184 $stmt = new $stmtClass($this, $sql);
185 $stmt->setFetchMode($this->_fetchMode);
186 return $stmt;
187 }
188
189 /**
190 * Gets the last ID generated automatically by an IDENTITY/AUTOINCREMENT column.
191 *
192 * As a convention, on RDBMS brands that support sequences
193 * (e.g. Oracle, PostgreSQL, DB2), this method forms the name of a sequence
194 * from the arguments and returns the last id generated by that sequence.
195 * On RDBMS brands that support IDENTITY/AUTOINCREMENT columns, this method
196 * returns the last value generated for such a column, and the table name
197 * argument is disregarded.
198 *
199 * On RDBMS brands that don't support sequences, $tableName and $primaryKey
200 * are ignored.
201 *
202 * @param string $tableName OPTIONAL Name of table.
203 * @param string $primaryKey OPTIONAL Name of primary key column.
204 * @return string
205 */
206 public function lastInsertId($tableName = null, $primaryKey = null)
207 {
208 $this->_connect();
209 return $this->_connection->lastInsertId();
210 }
211
212 /**
213 * Special handling for PDO query().
214 * All bind parameter names must begin with ':'
215 *
216 * @param string|Zend_Db_Select $sql The SQL statement with placeholders.
217 * @param array $bind An array of data to bind to the placeholders.
218 * @return Zend_Db_Statement_Pdo
219 * @throws Zend_Db_Adapter_Exception To re-throw PDOException.
220 */
221 public function query($sql, $bind = array())
222 {
223 if (empty($bind) && $sql instanceof Zend_Db_Select) {
224 $bind = $sql->getBind();
225 }
226
227 if (is_array($bind)) {
228 foreach ($bind as $name => $value) {
229 if (!is_int($name) && !preg_match('/^:/', $name)) {
230 $newName = ":$name";
231 unset($bind[$name]);
232 $bind[$newName] = $value;
233 }
234 }
235 }
236
237 try {
238 return parent::query($sql, $bind);
239 } catch (PDOException $e) {
240 /**
241 * @see Zend_Db_Statement_Exception
242 */
243 require_once 'Zend/Db/Statement/Exception.php';
244 throw new Zend_Db_Statement_Exception($e->getMessage(), $e->getCode(), $e);
245 }
246 }
247
248 /**
249 * Executes an SQL statement and return the number of affected rows
250 *
251 * @param mixed $sql The SQL statement with placeholders.
252 * May be a string or Zend_Db_Select.
253 * @return integer Number of rows that were modified
254 * or deleted by the SQL statement
255 */
256 public function exec($sql)
257 {
258 if ($sql instanceof Zend_Db_Select) {
259 $sql = $sql->assemble();
260 }
261
262 try {
263 $affected = $this->getConnection()->exec($sql);
264
265 if ($affected === false) {
266 $errorInfo = $this->getConnection()->errorInfo();
267 /**
268 * @see Zend_Db_Adapter_Exception
269 */
270 require_once 'Zend/Db/Adapter/Exception.php';
271 throw new Zend_Db_Adapter_Exception($errorInfo[2]);
272 }
273
274 return $affected;
275 } catch (PDOException $e) {
276 /**
277 * @see Zend_Db_Adapter_Exception
278 */
279 require_once 'Zend/Db/Adapter/Exception.php';
280 throw new Zend_Db_Adapter_Exception($e->getMessage(), $e->getCode(), $e);
281 }
282 }
283
284 /**
285 * Quote a raw string.
286 *
287 * @param string $value Raw string
288 * @return string Quoted string
289 */
290 protected function _quote($value)
291 {
292 if (is_int($value) || is_float($value)) {
293 return $value;
294 }
295 $this->_connect();
296 return $this->_connection->quote($value);
297 }
298
299 /**
300 * Begin a transaction.
301 */
302 protected function _beginTransaction()
303 {
304 $this->_connect();
305 $this->_connection->beginTransaction();
306 }
307
308 /**
309 * Commit a transaction.
310 */
311 protected function _commit()
312 {
313 $this->_connect();
314 $this->_connection->commit();
315 }
316
317 /**
318 * Roll-back a transaction.
319 */
320 protected function _rollBack() {
321 $this->_connect();
322 $this->_connection->rollBack();
323 }
324
325 /**
326 * Set the PDO fetch mode.
327 *
328 * @todo Support FETCH_CLASS and FETCH_INTO.
329 *
330 * @param int $mode A PDO fetch mode.
331 * @return void
332 * @throws Zend_Db_Adapter_Exception
333 */
334 public function setFetchMode($mode)
335 {
336 //check for PDO extension
337 if (!extension_loaded('pdo')) {
338 /**
339 * @see Zend_Db_Adapter_Exception
340 */
341 require_once 'Zend/Db/Adapter/Exception.php';
342 throw new Zend_Db_Adapter_Exception('The PDO extension is required for this adapter but the extension is not loaded');
343 }
344 switch ($mode) {
345 case PDO::FETCH_LAZY:
346 case PDO::FETCH_ASSOC:
347 case PDO::FETCH_NUM:
348 case PDO::FETCH_BOTH:
349 case PDO::FETCH_NAMED:
350 case PDO::FETCH_OBJ:
351 $this->_fetchMode = $mode;
352 break;
353 default:
354 /**
355 * @see Zend_Db_Adapter_Exception
356 */
357 require_once 'Zend/Db/Adapter/Exception.php';
358 throw new Zend_Db_Adapter_Exception("Invalid fetch mode '$mode' specified");
359 break;
360 }
361 }
362
363 /**
364 * Check if the adapter supports real SQL parameters.
365 *
366 * @param string $type 'positional' or 'named'
367 * @return bool
368 */
369 public function supportsParameters($type)
370 {
371 switch ($type) {
372 case 'positional':
373 case 'named':
374 default:
375 return true;
376 }
377 }
378
379 /**
380 * Retrieve server version in PHP style
381 *
382 * @return string
383 */
384 public function getServerVersion()
385 {
386 $this->_connect();
387 try {
388 $version = $this->_connection->getAttribute(PDO::ATTR_SERVER_VERSION);
389 } catch (PDOException $e) {
390 // In case of the driver doesn't support getting attributes
391 return null;
392 }
393 $matches = null;
394 if (preg_match('/((?:[0-9]{1,2}\.){1,3}[0-9]{1,2})/', $version, $matches)) {
395 return $matches[1];
396 } else {
397 return null;
398 }
399 }
400 }
401
402
-
open/home/peruvian/subdomains/m.peruvianvip.com/vendor/zendframework/zendframework1/library/Zend/Db/Table/Abstract.php
Zend_Db_Adapter_Pdo_Abstract->query(Zend_Db_Table_Select)
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 Table
18 * @copyright Copyright (c) 2005-2015 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 /**
24 * @see Zend_Db_Adapter_Abstract
25 */
26 require_once 'Zend/Db/Adapter/Abstract.php';
27
28 /**
29 * @see Zend_Db_Adapter_Abstract
30 */
31 require_once 'Zend/Db/Select.php';
32
33 /**
34 * @see Zend_Db
35 */
36 require_once 'Zend/Db.php';
37
38 /**
39 * Class for SQL table interface.
40 *
41 * @category Zend
42 * @package Zend_Db
43 * @subpackage Table
44 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
45 * @license http://framework.zend.com/license/new-bsd New BSD License
46 */
47 abstract class Zend_Db_Table_Abstract
48 {
49
50 const ADAPTER = 'db';
51 const DEFINITION = 'definition';
52 const DEFINITION_CONFIG_NAME = 'definitionConfigName';
53 const SCHEMA = 'schema';
54 const NAME = 'name';
55 const PRIMARY = 'primary';
56 const COLS = 'cols';
57 const METADATA = 'metadata';
58 const METADATA_CACHE = 'metadataCache';
59 const METADATA_CACHE_IN_CLASS = 'metadataCacheInClass';
60 const ROW_CLASS = 'rowClass';
61 const ROWSET_CLASS = 'rowsetClass';
62 const REFERENCE_MAP = 'referenceMap';
63 const DEPENDENT_TABLES = 'dependentTables';
64 const SEQUENCE = 'sequence';
65
66 const COLUMNS = 'columns';
67 const REF_TABLE_CLASS = 'refTableClass';
68 const REF_COLUMNS = 'refColumns';
69 const ON_DELETE = 'onDelete';
70 const ON_UPDATE = 'onUpdate';
71
72 const CASCADE = 'cascade';
73 const CASCADE_RECURSE = 'cascadeRecurse';
74 const RESTRICT = 'restrict';
75 const SET_NULL = 'setNull';
76
77 const DEFAULT_NONE = 'defaultNone';
78 const DEFAULT_CLASS = 'defaultClass';
79 const DEFAULT_DB = 'defaultDb';
80
81 const SELECT_WITH_FROM_PART = true;
82 const SELECT_WITHOUT_FROM_PART = false;
83
84 /**
85 * Default Zend_Db_Adapter_Abstract object.
86 *
87 * @var Zend_Db_Adapter_Abstract
88 */
89 protected static $_defaultDb;
90
91 /**
92 * Optional Zend_Db_Table_Definition object
93 *
94 * @var unknown_type
95 */
96 protected $_definition = null;
97
98 /**
99 * Optional definition config name used in concrete implementation
100 *
101 * @var string
102 */
103 protected $_definitionConfigName = null;
104
105 /**
106 * Default cache for information provided by the adapter's describeTable() method.
107 *
108 * @var Zend_Cache_Core
109 */
110 protected static $_defaultMetadataCache = null;
111
112 /**
113 * Zend_Db_Adapter_Abstract object.
114 *
115 * @var Zend_Db_Adapter_Abstract
116 */
117 protected $_db;
118
119 /**
120 * The schema name (default null means current schema)
121 *
122 * @var array
123 */
124 protected $_schema = null;
125
126 /**
127 * The table name.
128 *
129 * @var string
130 */
131 protected $_name = null;
132
133 /**
134 * The table column names derived from Zend_Db_Adapter_Abstract::describeTable().
135 *
136 * @var array
137 */
138 protected $_cols;
139
140 /**
141 * The primary key column or columns.
142 * A compound key should be declared as an array.
143 * You may declare a single-column primary key
144 * as a string.
145 *
146 * @var mixed
147 */
148 protected $_primary = null;
149
150 /**
151 * If your primary key is a compound key, and one of the columns uses
152 * an auto-increment or sequence-generated value, set _identity
153 * to the ordinal index in the $_primary array for that column.
154 * Note this index is the position of the column in the primary key,
155 * not the position of the column in the table. The primary key
156 * array is 1-based.
157 *
158 * @var integer
159 */
160 protected $_identity = 1;
161
162 /**
163 * Define the logic for new values in the primary key.
164 * May be a string, boolean true, or boolean false.
165 *
166 * @var mixed
167 */
168 protected $_sequence = true;
169
170 /**
171 * Information provided by the adapter's describeTable() method.
172 *
173 * @var array
174 */
175 protected $_metadata = array();
176
177 /**
178 * Cache for information provided by the adapter's describeTable() method.
179 *
180 * @var Zend_Cache_Core
181 */
182 protected $_metadataCache = null;
183
184 /**
185 * Flag: whether or not to cache metadata in the class
186 * @var bool
187 */
188 protected $_metadataCacheInClass = true;
189
190 /**
191 * Classname for row
192 *
193 * @var string
194 */
195 protected $_rowClass = 'Zend_Db_Table_Row';
196
197 /**
198 * Classname for rowset
199 *
200 * @var string
201 */
202 protected $_rowsetClass = 'Zend_Db_Table_Rowset';
203
204 /**
205 * Associative array map of declarative referential integrity rules.
206 * This array has one entry per foreign key in the current table.
207 * Each key is a mnemonic name for one reference rule.
208 *
209 * Each value is also an associative array, with the following keys:
210 * - columns = array of names of column(s) in the child table.
211 * - refTableClass = class name of the parent table.
212 * - refColumns = array of names of column(s) in the parent table,
213 * in the same order as those in the 'columns' entry.
214 * - onDelete = "cascade" means that a delete in the parent table also
215 * causes a delete of referencing rows in the child table.
216 * - onUpdate = "cascade" means that an update of primary key values in
217 * the parent table also causes an update of referencing
218 * rows in the child table.
219 *
220 * @var array
221 */
222 protected $_referenceMap = array();
223
224 /**
225 * Simple array of class names of tables that are "children" of the current
226 * table, in other words tables that contain a foreign key to this one.
227 * Array elements are not table names; they are class names of classes that
228 * extend Zend_Db_Table_Abstract.
229 *
230 * @var array
231 */
232 protected $_dependentTables = array();
233
234
235 protected $_defaultSource = self::DEFAULT_NONE;
236 protected $_defaultValues = array();
237
238 /**
239 * Constructor.
240 *
241 * Supported params for $config are:
242 * - db = user-supplied instance of database connector,
243 * or key name of registry instance.
244 * - name = table name.
245 * - primary = string or array of primary key(s).
246 * - rowClass = row class name.
247 * - rowsetClass = rowset class name.
248 * - referenceMap = array structure to declare relationship
249 * to parent tables.
250 * - dependentTables = array of child tables.
251 * - metadataCache = cache for information from adapter describeTable().
252 *
253 * @param mixed $config Array of user-specified config options, or just the Db Adapter.
254 * @return void
255 */
256 public function __construct($config = array())
257 {
258 /**
259 * Allow a scalar argument to be the Adapter object or Registry key.
260 */
261 if (!is_array($config)) {
262 $config = array(self::ADAPTER => $config);
263 }
264
265 if ($config) {
266 $this->setOptions($config);
267 }
268
269 $this->_setup();
270 $this->init();
271 }
272
273 /**
274 * setOptions()
275 *
276 * @param array $options
277 * @return Zend_Db_Table_Abstract
278 */
279 public function setOptions(Array $options)
280 {
281 foreach ($options as $key => $value) {
282 switch ($key) {
283 case self::ADAPTER:
284 $this->_setAdapter($value);
285 break;
286 case self::DEFINITION:
287 $this->setDefinition($value);
288 break;
289 case self::DEFINITION_CONFIG_NAME:
290 $this->setDefinitionConfigName($value);
291 break;
292 case self::SCHEMA:
293 $this->_schema = (string) $value;
294 break;
295 case self::NAME:
296 $this->_name = (string) $value;
297 break;
298 case self::PRIMARY:
299 $this->_primary = (array) $value;
300 break;
301 case self::ROW_CLASS:
302 $this->setRowClass($value);
303 break;
304 case self::ROWSET_CLASS:
305 $this->setRowsetClass($value);
306 break;
307 case self::REFERENCE_MAP:
308 $this->setReferences($value);
309 break;
310 case self::DEPENDENT_TABLES:
311 $this->setDependentTables($value);
312 break;
313 case self::METADATA_CACHE:
314 $this->_setMetadataCache($value);
315 break;
316 case self::METADATA_CACHE_IN_CLASS:
317 $this->setMetadataCacheInClass($value);
318 break;
319 case self::SEQUENCE:
320 $this->_setSequence($value);
321 break;
322 default:
323 // ignore unrecognized configuration directive
324 break;
325 }
326 }
327
328 return $this;
329 }
330
331 /**
332 * setDefinition()
333 *
334 * @param Zend_Db_Table_Definition $definition
335 * @return Zend_Db_Table_Abstract
336 */
337 public function setDefinition(Zend_Db_Table_Definition $definition)
338 {
339 $this->_definition = $definition;
340 return $this;
341 }
342
343 /**
344 * getDefinition()
345 *
346 * @return Zend_Db_Table_Definition|null
347 */
348 public function getDefinition()
349 {
350 return $this->_definition;
351 }
352
353 /**
354 * setDefinitionConfigName()
355 *
356 * @param string $definition
357 * @return Zend_Db_Table_Abstract
358 */
359 public function setDefinitionConfigName($definitionConfigName)
360 {
361 $this->_definitionConfigName = $definitionConfigName;
362 return $this;
363 }
364
365 /**
366 * getDefinitionConfigName()
367 *
368 * @return string
369 */
370 public function getDefinitionConfigName()
371 {
372 return $this->_definitionConfigName;
373 }
374
375 /**
376 * @param string $classname
377 * @return Zend_Db_Table_Abstract Provides a fluent interface
378 */
379 public function setRowClass($classname)
380 {
381 $this->_rowClass = (string) $classname;
382
383 return $this;
384 }
385
386 /**
387 * @return string
388 */
389 public function getRowClass()
390 {
391 return $this->_rowClass;
392 }
393
394 /**
395 * @param string $classname
396 * @return Zend_Db_Table_Abstract Provides a fluent interface
397 */
398 public function setRowsetClass($classname)
399 {
400 $this->_rowsetClass = (string) $classname;
401
402 return $this;
403 }
404
405 /**
406 * @return string
407 */
408 public function getRowsetClass()
409 {
410 return $this->_rowsetClass;
411 }
412
413 /**
414 * Add a reference to the reference map
415 *
416 * @param string $ruleKey
417 * @param string|array $columns
418 * @param string $refTableClass
419 * @param string|array $refColumns
420 * @param string $onDelete
421 * @param string $onUpdate
422 * @return Zend_Db_Table_Abstract
423 */
424 public function addReference($ruleKey, $columns, $refTableClass, $refColumns,
425 $onDelete = null, $onUpdate = null)
426 {
427 $reference = array(self::COLUMNS => (array) $columns,
428 self::REF_TABLE_CLASS => $refTableClass,
429 self::REF_COLUMNS => (array) $refColumns);
430
431 if (!empty($onDelete)) {
432 $reference[self::ON_DELETE] = $onDelete;
433 }
434
435 if (!empty($onUpdate)) {
436 $reference[self::ON_UPDATE] = $onUpdate;
437 }
438
439 $this->_referenceMap[$ruleKey] = $reference;
440
441 return $this;
442 }
443
444 /**
445 * @param array $referenceMap
446 * @return Zend_Db_Table_Abstract Provides a fluent interface
447 */
448 public function setReferences(array $referenceMap)
449 {
450 $this->_referenceMap = $referenceMap;
451
452 return $this;
453 }
454
455 /**
456 * @param string $tableClassname
457 * @param string $ruleKey OPTIONAL
458 * @return array
459 * @throws Zend_Db_Table_Exception
460 */
461 public function getReference($tableClassname, $ruleKey = null)
462 {
463 $thisClass = get_class($this);
464 if ($thisClass === 'Zend_Db_Table') {
465 $thisClass = $this->_definitionConfigName;
466 }
467 $refMap = $this->_getReferenceMapNormalized();
468 if ($ruleKey !== null) {
469 if (!isset($refMap[$ruleKey])) {
470 require_once "Zend/Db/Table/Exception.php";
471 throw new Zend_Db_Table_Exception("No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname");
472 }
473 if ($refMap[$ruleKey][self::REF_TABLE_CLASS] != $tableClassname) {
474 require_once "Zend/Db/Table/Exception.php";
475 throw new Zend_Db_Table_Exception("Reference rule \"$ruleKey\" does not reference table $tableClassname");
476 }
477 return $refMap[$ruleKey];
478 }
479 foreach ($refMap as $reference) {
480 if ($reference[self::REF_TABLE_CLASS] == $tableClassname) {
481 return $reference;
482 }
483 }
484 require_once "Zend/Db/Table/Exception.php";
485 throw new Zend_Db_Table_Exception("No reference from table $thisClass to table $tableClassname");
486 }
487
488 /**
489 * @param array $dependentTables
490 * @return Zend_Db_Table_Abstract Provides a fluent interface
491 */
492 public function setDependentTables(array $dependentTables)
493 {
494 $this->_dependentTables = $dependentTables;
495
496 return $this;
497 }
498
499 /**
500 * @return array
501 */
502 public function getDependentTables()
503 {
504 return $this->_dependentTables;
505 }
506
507 /**
508 * set the defaultSource property - this tells the table class where to find default values
509 *
510 * @param string $defaultSource
511 * @return Zend_Db_Table_Abstract
512 */
513 public function setDefaultSource($defaultSource = self::DEFAULT_NONE)
514 {
515 if (!in_array($defaultSource, array(self::DEFAULT_CLASS, self::DEFAULT_DB, self::DEFAULT_NONE))) {
516 $defaultSource = self::DEFAULT_NONE;
517 }
518
519 $this->_defaultSource = $defaultSource;
520 return $this;
521 }
522
523 /**
524 * returns the default source flag that determines where defaultSources come from
525 *
526 * @return unknown
527 */
528 public function getDefaultSource()
529 {
530 return $this->_defaultSource;
531 }
532
533 /**
534 * set the default values for the table class
535 *
536 * @param array $defaultValues
537 * @return Zend_Db_Table_Abstract
538 */
539 public function setDefaultValues(Array $defaultValues)
540 {
541 foreach ($defaultValues as $defaultName => $defaultValue) {
542 if (array_key_exists($defaultName, $this->_metadata)) {
543 $this->_defaultValues[$defaultName] = $defaultValue;
544 }
545 }
546 return $this;
547 }
548
549 public function getDefaultValues()
550 {
551 return $this->_defaultValues;
552 }
553
554
555 /**
556 * Sets the default Zend_Db_Adapter_Abstract for all Zend_Db_Table objects.
557 *
558 * @param mixed $db Either an Adapter object, or a string naming a Registry key
559 * @return void
560 */
561 public static function setDefaultAdapter($db = null)
562 {
563 self::$_defaultDb = self::_setupAdapter($db);
564 }
565
566 /**
567 * Gets the default Zend_Db_Adapter_Abstract for all Zend_Db_Table objects.
568 *
569 * @return Zend_Db_Adapter_Abstract or null
570 */
571 public static function getDefaultAdapter()
572 {
573 return self::$_defaultDb;
574 }
575
576 /**
577 * @param mixed $db Either an Adapter object, or a string naming a Registry key
578 * @return Zend_Db_Table_Abstract Provides a fluent interface
579 */
580 protected function _setAdapter($db)
581 {
582 $this->_db = self::_setupAdapter($db);
583 return $this;
584 }
585
586 /**
587 * Gets the Zend_Db_Adapter_Abstract for this particular Zend_Db_Table object.
588 *
589 * @return Zend_Db_Adapter_Abstract
590 */
591 public function getAdapter()
592 {
593 return $this->_db;
594 }
595
596 /**
597 * @param mixed $db Either an Adapter object, or a string naming a Registry key
598 * @return Zend_Db_Adapter_Abstract
599 * @throws Zend_Db_Table_Exception
600 */
601 protected static function _setupAdapter($db)
602 {
603 if ($db === null) {
604 return null;
605 }
606 if (is_string($db)) {
607 require_once 'Zend/Registry.php';
608 $db = Zend_Registry::get($db);
609 }
610 if (!$db instanceof Zend_Db_Adapter_Abstract) {
611 require_once 'Zend/Db/Table/Exception.php';
612 throw new Zend_Db_Table_Exception('Argument must be of type Zend_Db_Adapter_Abstract, or a Registry key where a Zend_Db_Adapter_Abstract object is stored');
613 }
614 return $db;
615 }
616
617 /**
618 * Sets the default metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
619 *
620 * If $defaultMetadataCache is null, then no metadata cache is used by default.
621 *
622 * @param mixed $metadataCache Either a Cache object, or a string naming a Registry key
623 * @return void
624 */
625 public static function setDefaultMetadataCache($metadataCache = null)
626 {
627 self::$_defaultMetadataCache = self::_setupMetadataCache($metadataCache);
628 }
629
630 /**
631 * Gets the default metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
632 *
633 * @return Zend_Cache_Core or null
634 */
635 public static function getDefaultMetadataCache()
636 {
637 return self::$_defaultMetadataCache;
638 }
639
640 /**
641 * Sets the metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
642 *
643 * If $metadataCache is null, then no metadata cache is used. Since there is no opportunity to reload metadata
644 * after instantiation, this method need not be public, particularly because that it would have no effect
645 * results in unnecessary API complexity. To configure the metadata cache, use the metadataCache configuration
646 * option for the class constructor upon instantiation.
647 *
648 * @param mixed $metadataCache Either a Cache object, or a string naming a Registry key
649 * @return Zend_Db_Table_Abstract Provides a fluent interface
650 */
651 protected function _setMetadataCache($metadataCache)
652 {
653 $this->_metadataCache = self::_setupMetadataCache($metadataCache);
654 return $this;
655 }
656
657 /**
658 * Gets the metadata cache for information returned by Zend_Db_Adapter_Abstract::describeTable().
659 *
660 * @return Zend_Cache_Core or null
661 */
662 public function getMetadataCache()
663 {
664 return $this->_metadataCache;
665 }
666
667 /**
668 * Indicate whether metadata should be cached in the class for the duration
669 * of the instance
670 *
671 * @param bool $flag
672 * @return Zend_Db_Table_Abstract
673 */
674 public function setMetadataCacheInClass($flag)
675 {
676 $this->_metadataCacheInClass = (bool) $flag;
677 return $this;
678 }
679
680 /**
681 * Retrieve flag indicating if metadata should be cached for duration of
682 * instance
683 *
684 * @return bool
685 */
686 public function metadataCacheInClass()
687 {
688 return $this->_metadataCacheInClass;
689 }
690
691 /**
692 * @param mixed $metadataCache Either a Cache object, or a string naming a Registry key
693 * @return Zend_Cache_Core
694 * @throws Zend_Db_Table_Exception
695 */
696 protected static function _setupMetadataCache($metadataCache)
697 {
698 if ($metadataCache === null) {
699 return null;
700 }
701 if (is_string($metadataCache)) {
702 require_once 'Zend/Registry.php';
703 $metadataCache = Zend_Registry::get($metadataCache);
704 }
705 if (!$metadataCache instanceof Zend_Cache_Core) {
706 require_once 'Zend/Db/Table/Exception.php';
707 throw new Zend_Db_Table_Exception('Argument must be of type Zend_Cache_Core, or a Registry key where a Zend_Cache_Core object is stored');
708 }
709 return $metadataCache;
710 }
711
712 /**
713 * Sets the sequence member, which defines the behavior for generating
714 * primary key values in new rows.
715 * - If this is a string, then the string names the sequence object.
716 * - If this is boolean true, then the key uses an auto-incrementing
717 * or identity mechanism.
718 * - If this is boolean false, then the key is user-defined.
719 * Use this for natural keys, for example.
720 *
721 * @param mixed $sequence
722 * @return Zend_Db_Table_Adapter_Abstract Provides a fluent interface
723 */
724 protected function _setSequence($sequence)
725 {
726 $this->_sequence = $sequence;
727
728 return $this;
729 }
730
731 /**
732 * Turnkey for initialization of a table object.
733 * Calls other protected methods for individual tasks, to make it easier
734 * for a subclass to override part of the setup logic.
735 *
736 * @return void
737 */
738 protected function _setup()
739 {
740 $this->_setupDatabaseAdapter();
741 $this->_setupTableName();
742 }
743
744 /**
745 * Initialize database adapter.
746 *
747 * @return void
748 * @throws Zend_Db_Table_Exception
749 */
750 protected function _setupDatabaseAdapter()
751 {
752 if (! $this->_db) {
753 $this->_db = self::getDefaultAdapter();
754 if (!$this->_db instanceof Zend_Db_Adapter_Abstract) {
755 require_once 'Zend/Db/Table/Exception.php';
756 throw new Zend_Db_Table_Exception('No adapter found for ' . get_class($this));
757 }
758 }
759 }
760
761 /**
762 * Initialize table and schema names.
763 *
764 * If the table name is not set in the class definition,
765 * use the class name itself as the table name.
766 *
767 * A schema name provided with the table name (e.g., "schema.table") overrides
768 * any existing value for $this->_schema.
769 *
770 * @return void
771 */
772 protected function _setupTableName()
773 {
774 if (! $this->_name) {
775 $this->_name = get_class($this);
776 } else if (strpos($this->_name, '.')) {
777 list($this->_schema, $this->_name) = explode('.', $this->_name);
778 }
779 }
780
781 /**
782 * Initializes metadata.
783 *
784 * If metadata cannot be loaded from cache, adapter's describeTable() method is called to discover metadata
785 * information. Returns true if and only if the metadata are loaded from cache.
786 *
787 * @return boolean
788 * @throws Zend_Db_Table_Exception
789 */
790 protected function _setupMetadata()
791 {
792 if ($this->metadataCacheInClass() && (count($this->_metadata) > 0)) {
793 return true;
794 }
795
796 // Assume that metadata will be loaded from cache
797 $isMetadataFromCache = true;
798
799 // If $this has no metadata cache but the class has a default metadata cache
800 if (null === $this->_metadataCache && null !== self::$_defaultMetadataCache) {
801 // Make $this use the default metadata cache of the class
802 $this->_setMetadataCache(self::$_defaultMetadataCache);
803 }
804
805 // If $this has a metadata cache
806 if (null !== $this->_metadataCache) {
807 // Define the cache identifier where the metadata are saved
808
809 //get db configuration
810 $dbConfig = $this->_db->getConfig();
811
812 $port = isset($dbConfig['options']['port'])
813 ? ':'.$dbConfig['options']['port']
814 : (isset($dbConfig['port'])
815 ? ':'.$dbConfig['port']
816 : null);
817
818 $host = isset($dbConfig['options']['host'])
819 ? ':'.$dbConfig['options']['host']
820 : (isset($dbConfig['host'])
821 ? ':'.$dbConfig['host']
822 : null);
823
824 // Define the cache identifier where the metadata are saved
825 $cacheId = md5( // port:host/dbname:schema.table (based on availabilty)
826 $port . $host . '/'. $dbConfig['dbname'] . ':'
827 . $this->_schema. '.' . $this->_name
828 );
829 }
830
831 // If $this has no metadata cache or metadata cache misses
832 if (null === $this->_metadataCache || !($metadata = $this->_metadataCache->load($cacheId))) {
833 // Metadata are not loaded from cache
834 $isMetadataFromCache = false;
835 // Fetch metadata from the adapter's describeTable() method
836 $metadata = $this->_db->describeTable($this->_name, $this->_schema);
837 // If $this has a metadata cache, then cache the metadata
838 if (null !== $this->_metadataCache && !$this->_metadataCache->save($metadata, $cacheId)) {
839 trigger_error('Failed saving metadata to metadataCache', E_USER_NOTICE);
840 }
841 }
842
843 // Assign the metadata to $this
844 $this->_metadata = $metadata;
845
846 // Return whether the metadata were loaded from cache
847 return $isMetadataFromCache;
848 }
849
850 /**
851 * Retrieve table columns
852 *
853 * @return array
854 */
855 protected function _getCols()
856 {
857 if (null === $this->_cols) {
858 $this->_setupMetadata();
859 $this->_cols = array_keys($this->_metadata);
860 }
861 return $this->_cols;
862 }
863
864 /**
865 * Initialize primary key from metadata.
866 * If $_primary is not defined, discover primary keys
867 * from the information returned by describeTable().
868 *
869 * @return void
870 * @throws Zend_Db_Table_Exception
871 */
872 protected function _setupPrimaryKey()
873 {
874 if (!$this->_primary) {
875 $this->_setupMetadata();
876 $this->_primary = array();
877 foreach ($this->_metadata as $col) {
878 if ($col['PRIMARY']) {
879 $this->_primary[ $col['PRIMARY_POSITION'] ] = $col['COLUMN_NAME'];
880 if ($col['IDENTITY']) {
881 $this->_identity = $col['PRIMARY_POSITION'];
882 }
883 }
884 }
885 // if no primary key was specified and none was found in the metadata
886 // then throw an exception.
887 if (empty($this->_primary)) {
888 require_once 'Zend/Db/Table/Exception.php';
889 throw new Zend_Db_Table_Exception("A table must have a primary key, but none was found for table '{$this->_name}'");
890 }
891 } else if (!is_array($this->_primary)) {
892 $this->_primary = array(1 => $this->_primary);
893 } else if (isset($this->_primary[0])) {
894 array_unshift($this->_primary, null);
895 unset($this->_primary[0]);
896 }
897
898 $cols = $this->_getCols();
899 if (! array_intersect((array) $this->_primary, $cols) == (array) $this->_primary) {
900 require_once 'Zend/Db/Table/Exception.php';
901 throw new Zend_Db_Table_Exception("Primary key column(s) ("
902 . implode(',', (array) $this->_primary)
903 . ") are not columns in this table ("
904 . implode(',', $cols)
905 . ")");
906 }
907
908 $primary = (array) $this->_primary;
909 $pkIdentity = $primary[(int) $this->_identity];
910
911 /**
912 * Special case for PostgreSQL: a SERIAL key implicitly uses a sequence
913 * object whose name is "<table>_<column>_seq".
914 */
915 if ($this->_sequence === true && $this->_db instanceof Zend_Db_Adapter_Pdo_Pgsql) {
916 $this->_sequence = $this->_db->quoteIdentifier("{$this->_name}_{$pkIdentity}_seq");
917 if ($this->_schema) {
918 $this->_sequence = $this->_db->quoteIdentifier($this->_schema) . '.' . $this->_sequence;
919 }
920 }
921 }
922
923 /**
924 * Returns a normalized version of the reference map
925 *
926 * @return array
927 */
928 protected function _getReferenceMapNormalized()
929 {
930 $referenceMapNormalized = array();
931
932 foreach ($this->_referenceMap as $rule => $map) {
933
934 $referenceMapNormalized[$rule] = array();
935
936 foreach ($map as $key => $value) {
937 switch ($key) {
938
939 // normalize COLUMNS and REF_COLUMNS to arrays
940 case self::COLUMNS:
941 case self::REF_COLUMNS:
942 if (!is_array($value)) {
943 $referenceMapNormalized[$rule][$key] = array($value);
944 } else {
945 $referenceMapNormalized[$rule][$key] = $value;
946 }
947 break;
948
949 // other values are copied as-is
950 default:
951 $referenceMapNormalized[$rule][$key] = $value;
952 break;
953 }
954 }
955 }
956
957 return $referenceMapNormalized;
958 }
959
960 /**
961 * Initialize object
962 *
963 * Called from {@link __construct()} as final step of object instantiation.
964 *
965 * @return void
966 */
967 public function init()
968 {
969 }
970
971 /**
972 * Returns table information.
973 *
974 * You can elect to return only a part of this information by supplying its key name,
975 * otherwise all information is returned as an array.
976 *
977 * @param string $key The specific info part to return OPTIONAL
978 * @return mixed
979 * @throws Zend_Db_Table_Exception
980 */
981 public function info($key = null)
982 {
983 $this->_setupPrimaryKey();
984
985 $info = array(
986 self::SCHEMA => $this->_schema,
987 self::NAME => $this->_name,
988 self::COLS => $this->_getCols(),
989 self::PRIMARY => (array) $this->_primary,
990 self::METADATA => $this->_metadata,
991 self::ROW_CLASS => $this->getRowClass(),
992 self::ROWSET_CLASS => $this->getRowsetClass(),
993 self::REFERENCE_MAP => $this->_referenceMap,
994 self::DEPENDENT_TABLES => $this->_dependentTables,
995 self::SEQUENCE => $this->_sequence
996 );
997
998 if ($key === null) {
999 return $info;
1000 }
1001
1002 if (!array_key_exists($key, $info)) {
1003 require_once 'Zend/Db/Table/Exception.php';
1004 throw new Zend_Db_Table_Exception('There is no table information for the key "' . $key . '"');
1005 }
1006
1007 return $info[$key];
1008 }
1009
1010 /**
1011 * Returns an instance of a Zend_Db_Table_Select object.
1012 *
1013 * @param bool $withFromPart Whether or not to include the from part of the select based on the table
1014 * @return Zend_Db_Table_Select
1015 */
1016 public function select($withFromPart = self::SELECT_WITHOUT_FROM_PART)
1017 {
1018 require_once 'Zend/Db/Table/Select.php';
1019 $select = new Zend_Db_Table_Select($this);
1020 if ($withFromPart == self::SELECT_WITH_FROM_PART) {
1021 $select->from($this->info(self::NAME), Zend_Db_Table_Select::SQL_WILDCARD, $this->info(self::SCHEMA));
1022 }
1023 return $select;
1024 }
1025
1026 /**
1027 * Inserts a new row.
1028 *
1029 * @param array $data Column-value pairs.
1030 * @return mixed The primary key of the row inserted.
1031 */
1032 public function insert(array $data)
1033 {
1034 $this->_setupPrimaryKey();
1035
1036 /**
1037 * Zend_Db_Table assumes that if you have a compound primary key
1038 * and one of the columns in the key uses a sequence,
1039 * it's the _first_ column in the compound key.
1040 */
1041 $primary = (array) $this->_primary;
1042 $pkIdentity = $primary[(int)$this->_identity];
1043
1044
1045 /**
1046 * If the primary key can be generated automatically, and no value was
1047 * specified in the user-supplied data, then omit it from the tuple.
1048 *
1049 * Note: this checks for sensible values in the supplied primary key
1050 * position of the data. The following values are considered empty:
1051 * null, false, true, '', array()
1052 */
1053 if (array_key_exists($pkIdentity, $data)) {
1054 if ($data[$pkIdentity] === null // null
1055 || $data[$pkIdentity] === '' // empty string
1056 || is_bool($data[$pkIdentity]) // boolean
1057 || (is_array($data[$pkIdentity]) && empty($data[$pkIdentity]))) { // empty array
1058 unset($data[$pkIdentity]);
1059 }
1060 }
1061
1062 /**
1063 * If this table uses a database sequence object and the data does not
1064 * specify a value, then get the next ID from the sequence and add it
1065 * to the row. We assume that only the first column in a compound
1066 * primary key takes a value from a sequence.
1067 */
1068 if (is_string($this->_sequence) && !isset($data[$pkIdentity])) {
1069 $data[$pkIdentity] = $this->_db->nextSequenceId($this->_sequence);
1070 }
1071
1072 /**
1073 * INSERT the new row.
1074 */
1075 $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
1076 $this->_db->insert($tableSpec, $data);
1077
1078 /**
1079 * Fetch the most recent ID generated by an auto-increment
1080 * or IDENTITY column, unless the user has specified a value,
1081 * overriding the auto-increment mechanism.
1082 */
1083 if ($this->_sequence === true && !isset($data[$pkIdentity])) {
1084 $data[$pkIdentity] = $this->_db->lastInsertId();
1085 }
1086
1087 /**
1088 * Return the primary key value if the PK is a single column,
1089 * else return an associative array of the PK column/value pairs.
1090 */
1091 $pkData = array_intersect_key($data, array_flip($primary));
1092 if (count($primary) == 1) {
1093 reset($pkData);
1094 return current($pkData);
1095 }
1096
1097 return $pkData;
1098 }
1099
1100 /**
1101 * Check if the provided column is an identity of the table
1102 *
1103 * @param string $column
1104 * @throws Zend_Db_Table_Exception
1105 * @return boolean
1106 */
1107 public function isIdentity($column)
1108 {
1109 $this->_setupPrimaryKey();
1110
1111 if (!isset($this->_metadata[$column])) {
1112 /**
1113 * @see Zend_Db_Table_Exception
1114 */
1115 require_once 'Zend/Db/Table/Exception.php';
1116
1117 throw new Zend_Db_Table_Exception('Column "' . $column . '" not found in table.');
1118 }
1119
1120 return (bool) $this->_metadata[$column]['IDENTITY'];
1121 }
1122
1123 /**
1124 * Updates existing rows.
1125 *
1126 * @param array $data Column-value pairs.
1127 * @param array|string $where An SQL WHERE clause, or an array of SQL WHERE clauses.
1128 * @return int The number of rows updated.
1129 */
1130 public function update(array $data, $where)
1131 {
1132 $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
1133 return $this->_db->update($tableSpec, $data, $where);
1134 }
1135
1136 /**
1137 * Called by a row object for the parent table's class during save() method.
1138 *
1139 * @param string $parentTableClassname
1140 * @param array $oldPrimaryKey
1141 * @param array $newPrimaryKey
1142 * @return int
1143 */
1144 public function _cascadeUpdate($parentTableClassname, array $oldPrimaryKey, array $newPrimaryKey)
1145 {
1146 $this->_setupMetadata();
1147 $rowsAffected = 0;
1148 foreach ($this->_getReferenceMapNormalized() as $map) {
1149 if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_UPDATE])) {
1150 switch ($map[self::ON_UPDATE]) {
1151 case self::CASCADE:
1152 $newRefs = array();
1153 $where = array();
1154 for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
1155 $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
1156 $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
1157 if (array_key_exists($refCol, $newPrimaryKey)) {
1158 $newRefs[$col] = $newPrimaryKey[$refCol];
1159 }
1160 $type = $this->_metadata[$col]['DATA_TYPE'];
1161 $where[] = $this->_db->quoteInto(
1162 $this->_db->quoteIdentifier($col, true) . ' = ?',
1163 $oldPrimaryKey[$refCol], $type);
1164 }
1165 $rowsAffected += $this->update($newRefs, $where);
1166 break;
1167 default:
1168 // no action
1169 break;
1170 }
1171 }
1172 }
1173 return $rowsAffected;
1174 }
1175
1176 /**
1177 * Deletes existing rows.
1178 *
1179 * @param array|string $where SQL WHERE clause(s).
1180 * @return int The number of rows deleted.
1181 */
1182 public function delete($where)
1183 {
1184 $depTables = $this->getDependentTables();
1185 if (!empty($depTables)) {
1186 $resultSet = $this->fetchAll($where);
1187 if (count($resultSet) > 0 ) {
1188 foreach ($resultSet as $row) {
1189 /**
1190 * Execute cascading deletes against dependent tables
1191 */
1192 foreach ($depTables as $tableClass) {
1193 $t = self::getTableFromString($tableClass, $this);
1194 $t->_cascadeDelete(
1195 get_class($this), $row->getPrimaryKey()
1196 );
1197 }
1198 }
1199 }
1200 }
1201
1202 $tableSpec = ($this->_schema ? $this->_schema . '.' : '') . $this->_name;
1203 return $this->_db->delete($tableSpec, $where);
1204 }
1205
1206 /**
1207 * Called by parent table's class during delete() method.
1208 *
1209 * @param string $parentTableClassname
1210 * @param array $primaryKey
1211 * @return int Number of affected rows
1212 */
1213 public function _cascadeDelete($parentTableClassname, array $primaryKey)
1214 {
1215 // setup metadata
1216 $this->_setupMetadata();
1217
1218 // get this class name
1219 $thisClass = get_class($this);
1220 if ($thisClass === 'Zend_Db_Table') {
1221 $thisClass = $this->_definitionConfigName;
1222 }
1223
1224 $rowsAffected = 0;
1225
1226 foreach ($this->_getReferenceMapNormalized() as $map) {
1227 if ($map[self::REF_TABLE_CLASS] == $parentTableClassname && isset($map[self::ON_DELETE])) {
1228
1229 $where = array();
1230
1231 // CASCADE or CASCADE_RECURSE
1232 if (in_array($map[self::ON_DELETE], array(self::CASCADE, self::CASCADE_RECURSE))) {
1233 for ($i = 0; $i < count($map[self::COLUMNS]); ++$i) {
1234 $col = $this->_db->foldCase($map[self::COLUMNS][$i]);
1235 $refCol = $this->_db->foldCase($map[self::REF_COLUMNS][$i]);
1236 $type = $this->_metadata[$col]['DATA_TYPE'];
1237 $where[] = $this->_db->quoteInto(
1238 $this->_db->quoteIdentifier($col, true) . ' = ?',
1239 $primaryKey[$refCol], $type);
1240 }
1241 }
1242
1243 // CASCADE_RECURSE
1244 if ($map[self::ON_DELETE] == self::CASCADE_RECURSE) {
1245
1246 /**
1247 * Execute cascading deletes against dependent tables
1248 */
1249 $depTables = $this->getDependentTables();
1250 if (!empty($depTables)) {
1251 foreach ($depTables as $tableClass) {
1252 $t = self::getTableFromString($tableClass, $this);
1253 foreach ($this->fetchAll($where) as $depRow) {
1254 $rowsAffected += $t->_cascadeDelete($thisClass, $depRow->getPrimaryKey());
1255 }
1256 }
1257 }
1258 }
1259
1260 // CASCADE or CASCADE_RECURSE
1261 if (in_array($map[self::ON_DELETE], array(self::CASCADE, self::CASCADE_RECURSE))) {
1262 $rowsAffected += $this->delete($where);
1263 }
1264
1265 }
1266 }
1267 return $rowsAffected;
1268 }
1269
1270 /**
1271 * Fetches rows by primary key. The argument specifies one or more primary
1272 * key value(s). To find multiple rows by primary key, the argument must
1273 * be an array.
1274 *
1275 * This method accepts a variable number of arguments. If the table has a
1276 * multi-column primary key, the number of arguments must be the same as
1277 * the number of columns in the primary key. To find multiple rows in a
1278 * table with a multi-column primary key, each argument must be an array
1279 * with the same number of elements.
1280 *
1281 * The find() method always returns a Rowset object, even if only one row
1282 * was found.
1283 *
1284 * @param mixed $key The value(s) of the primary keys.
1285 * @return Zend_Db_Table_Rowset_Abstract Row(s) matching the criteria.
1286 * @throws Zend_Db_Table_Exception
1287 */
1288 public function find()
1289 {
1290 $this->_setupPrimaryKey();
1291 $args = func_get_args();
1292 $keyNames = array_values((array) $this->_primary);
1293
1294 if (count($args) < count($keyNames)) {
1295 require_once 'Zend/Db/Table/Exception.php';
1296 throw new Zend_Db_Table_Exception("Too few columns for the primary key");
1297 }
1298
1299 if (count($args) > count($keyNames)) {
1300 require_once 'Zend/Db/Table/Exception.php';
1301 throw new Zend_Db_Table_Exception("Too many columns for the primary key");
1302 }
1303
1304 $whereList = array();
1305 $numberTerms = 0;
1306 foreach ($args as $keyPosition => $keyValues) {
1307 $keyValuesCount = count($keyValues);
1308 // Coerce the values to an array.
1309 // Don't simply typecast to array, because the values
1310 // might be Zend_Db_Expr objects.
1311 if (!is_array($keyValues)) {
1312 $keyValues = array($keyValues);
1313 }
1314 if ($numberTerms == 0) {
1315 $numberTerms = $keyValuesCount;
1316 } else if ($keyValuesCount != $numberTerms) {
1317 require_once 'Zend/Db/Table/Exception.php';
1318 throw new Zend_Db_Table_Exception("Missing value(s) for the primary key");
1319 }
1320 $keyValues = array_values($keyValues);
1321 for ($i = 0; $i < $keyValuesCount; ++$i) {
1322 if (!isset($whereList[$i])) {
1323 $whereList[$i] = array();
1324 }
1325 $whereList[$i][$keyPosition] = $keyValues[$i];
1326 }
1327 }
1328
1329 $whereClause = null;
1330 if (count($whereList)) {
1331 $whereOrTerms = array();
1332 $tableName = $this->_db->quoteTableAs($this->_name, null, true);
1333 foreach ($whereList as $keyValueSets) {
1334 $whereAndTerms = array();
1335 foreach ($keyValueSets as $keyPosition => $keyValue) {
1336 $type = $this->_metadata[$keyNames[$keyPosition]]['DATA_TYPE'];
1337 $columnName = $this->_db->quoteIdentifier($keyNames[$keyPosition], true);
1338 $whereAndTerms[] = $this->_db->quoteInto(
1339 $tableName . '.' . $columnName . ' = ?',
1340 $keyValue, $type);
1341 }
1342 $whereOrTerms[] = '(' . implode(' AND ', $whereAndTerms) . ')';
1343 }
1344 $whereClause = '(' . implode(' OR ', $whereOrTerms) . ')';
1345 }
1346
1347 // issue ZF-5775 (empty where clause should return empty rowset)
1348 if ($whereClause == null) {
1349 $rowsetClass = $this->getRowsetClass();
1350 if (!class_exists($rowsetClass)) {
1351 require_once 'Zend/Loader.php';
1352 Zend_Loader::loadClass($rowsetClass);
1353 }
1354 return new $rowsetClass(array('table' => $this, 'rowClass' => $this->getRowClass(), 'stored' => true));
1355 }
1356
1357 return $this->fetchAll($whereClause);
1358 }
1359
1360 /**
1361 * Fetches all rows.
1362 *
1363 * Honors the Zend_Db_Adapter fetch mode.
1364 *
1365 * @param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object.
1366 * @param string|array $order OPTIONAL An SQL ORDER clause.
1367 * @param int $count OPTIONAL An SQL LIMIT count.
1368 * @param int $offset OPTIONAL An SQL LIMIT offset.
1369 * @return Zend_Db_Table_Rowset_Abstract The row results per the Zend_Db_Adapter fetch mode.
1370 */
1371 public function fetchAll($where = null, $order = null, $count = null, $offset = null)
1372 {
1373 if (!($where instanceof Zend_Db_Table_Select)) {
1374 $select = $this->select();
1375
1376 if ($where !== null) {
1377 $this->_where($select, $where);
1378 }
1379
1380 if ($order !== null) {
1381 $this->_order($select, $order);
1382 }
1383
1384 if ($count !== null || $offset !== null) {
1385 $select->limit($count, $offset);
1386 }
1387
1388 } else {
1389 $select = $where;
1390 }
1391
1392 $rows = $this->_fetch($select);
1393
1394 $data = array(
1395 'table' => $this,
1396 'data' => $rows,
1397 'readOnly' => $select->isReadOnly(),
1398 'rowClass' => $this->getRowClass(),
1399 'stored' => true
1400 );
1401
1402 $rowsetClass = $this->getRowsetClass();
1403 if (!class_exists($rowsetClass)) {
1404 require_once 'Zend/Loader.php';
1405 Zend_Loader::loadClass($rowsetClass);
1406 }
1407 return new $rowsetClass($data);
1408 }
1409
1410 /**
1411 * Fetches one row in an object of type Zend_Db_Table_Row_Abstract,
1412 * or returns null if no row matches the specified criteria.
1413 *
1414 * @param string|array|Zend_Db_Table_Select $where OPTIONAL An SQL WHERE clause or Zend_Db_Table_Select object.
1415 * @param string|array $order OPTIONAL An SQL ORDER clause.
1416 * @param int $offset OPTIONAL An SQL OFFSET value.
1417 * @return Zend_Db_Table_Row_Abstract|null The row results per the
1418 * Zend_Db_Adapter fetch mode, or null if no row found.
1419 */
1420 public function fetchRow($where = null, $order = null, $offset = null)
1421 {
1422 if (!($where instanceof Zend_Db_Table_Select)) {
1423 $select = $this->select();
1424
1425 if ($where !== null) {
1426 $this->_where($select, $where);
1427 }
1428
1429 if ($order !== null) {
1430 $this->_order($select, $order);
1431 }
1432
1433 $select->limit(1, ((is_numeric($offset)) ? (int) $offset : null));
1434
1435 } else {
1436 $select = $where->limit(1, $where->getPart(Zend_Db_Select::LIMIT_OFFSET));
1437 }
1438
1439 $rows = $this->_fetch($select);
1440
1441 if (count($rows) == 0) {
1442 return null;
1443 }
1444
1445 $data = array(
1446 'table' => $this,
1447 'data' => $rows[0],
1448 'readOnly' => $select->isReadOnly(),
1449 'stored' => true
1450 );
1451
1452 $rowClass = $this->getRowClass();
1453 if (!class_exists($rowClass)) {
1454 require_once 'Zend/Loader.php';
1455 Zend_Loader::loadClass($rowClass);
1456 }
1457 return new $rowClass($data);
1458 }
1459
1460 /**
1461 * Fetches a new blank row (not from the database).
1462 *
1463 * @return Zend_Db_Table_Row_Abstract
1464 * @deprecated since 0.9.3 - use createRow() instead.
1465 */
1466 public function fetchNew()
1467 {
1468 return $this->createRow();
1469 }
1470
1471 /**
1472 * Fetches a new blank row (not from the database).
1473 *
1474 * @param array $data OPTIONAL data to populate in the new row.
1475 * @param string $defaultSource OPTIONAL flag to force default values into new row
1476 * @return Zend_Db_Table_Row_Abstract
1477 */
1478 public function createRow(array $data = array(), $defaultSource = null)
1479 {
1480 $cols = $this->_getCols();
1481 $defaults = array_combine($cols, array_fill(0, count($cols), null));
1482
1483 // nothing provided at call-time, take the class value
1484 if ($defaultSource == null) {
1485 $defaultSource = $this->_defaultSource;
1486 }
1487
1488 if (!in_array($defaultSource, array(self::DEFAULT_CLASS, self::DEFAULT_DB, self::DEFAULT_NONE))) {
1489 $defaultSource = self::DEFAULT_NONE;
1490 }
1491
1492 if ($defaultSource == self::DEFAULT_DB) {
1493 foreach ($this->_metadata as $metadataName => $metadata) {
1494 if (($metadata['DEFAULT'] != null) &&
1495 ($metadata['NULLABLE'] !== true || ($metadata['NULLABLE'] === true && isset($this->_defaultValues[$metadataName]) && $this->_defaultValues[$metadataName] === true)) &&
1496 (!(isset($this->_defaultValues[$metadataName]) && $this->_defaultValues[$metadataName] === false))) {
1497 $defaults[$metadataName] = $metadata['DEFAULT'];
1498 }
1499 }
1500 } elseif ($defaultSource == self::DEFAULT_CLASS && $this->_defaultValues) {
1501 foreach ($this->_defaultValues as $defaultName => $defaultValue) {
1502 if (array_key_exists($defaultName, $defaults)) {
1503 $defaults[$defaultName] = $defaultValue;
1504 }
1505 }
1506 }
1507
1508 $config = array(
1509 'table' => $this,
1510 'data' => $defaults,
1511 'readOnly' => false,
1512 'stored' => false
1513 );
1514
1515 $rowClass = $this->getRowClass();
1516 if (!class_exists($rowClass)) {
1517 require_once 'Zend/Loader.php';
1518 Zend_Loader::loadClass($rowClass);
1519 }
1520 $row = new $rowClass($config);
1521 $row->setFromArray($data);
1522 return $row;
1523 }
1524
1525 /**
1526 * Generate WHERE clause from user-supplied string or array
1527 *
1528 * @param string|array $where OPTIONAL An SQL WHERE clause.
1529 * @return Zend_Db_Table_Select
1530 */
1531 protected function _where(Zend_Db_Table_Select $select, $where)
1532 {
1533 $where = (array) $where;
1534
1535 foreach ($where as $key => $val) {
1536 // is $key an int?
1537 if (is_int($key)) {
1538 // $val is the full condition
1539 $select->where($val);
1540 } else {
1541 // $key is the condition with placeholder,
1542 // and $val is quoted into the condition
1543 $select->where($key, $val);
1544 }
1545 }
1546
1547 return $select;
1548 }
1549
1550 /**
1551 * Generate ORDER clause from user-supplied string or array
1552 *
1553 * @param string|array $order OPTIONAL An SQL ORDER clause.
1554 * @return Zend_Db_Table_Select
1555 */
1556 protected function _order(Zend_Db_Table_Select $select, $order)
1557 {
1558 if (!is_array($order)) {
1559 $order = array($order);
1560 }
1561
1562 foreach ($order as $val) {
1563 $select->order($val);
1564 }
1565
1566 return $select;
1567 }
1568
1569 /**
1570 * Support method for fetching rows.
1571 *
1572 * @param Zend_Db_Table_Select $select query options.
1573 * @return array An array containing the row results in FETCH_ASSOC mode.
1574 */
1575 protected function _fetch(Zend_Db_Table_Select $select)
1576 {
1577 $stmt = $this->_db->query($select);
1578 $data = $stmt->fetchAll(Zend_Db::FETCH_ASSOC);
1579 return $data;
1580 }
1581
1582 /**
1583 * Get table gateway object from string
1584 *
1585 * @param string $tableName
1586 * @param Zend_Db_Table_Abstract $referenceTable
1587 * @throws Zend_Db_Table_Row_Exception
1588 * @return Zend_Db_Table_Abstract
1589 */
1590 public static function getTableFromString($tableName, Zend_Db_Table_Abstract $referenceTable = null)
1591 {
1592 if ($referenceTable instanceof Zend_Db_Table_Abstract) {
1593 $tableDefinition = $referenceTable->getDefinition();
1594
1595 if ($tableDefinition !== null && $tableDefinition->hasTableConfig($tableName)) {
1596 return new Zend_Db_Table($tableName, $tableDefinition);
1597 }
1598 }
1599
1600 // assume the tableName is the class name
1601 if (!class_exists($tableName)) {
1602 try {
1603 require_once 'Zend/Loader.php';
1604 Zend_Loader::loadClass($tableName);
1605 } catch (Zend_Exception $e) {
1606 require_once 'Zend/Db/Table/Row/Exception.php';
1607 throw new Zend_Db_Table_Row_Exception($e->getMessage(), $e->getCode(), $e);
1608 }
1609 }
1610
1611 $options = array();
1612
1613 if ($referenceTable instanceof Zend_Db_Table_Abstract) {
1614 $options['db'] = $referenceTable->getAdapter();
1615 }
1616
1617 if (isset($tableDefinition) && $tableDefinition !== null) {
1618 $options[Zend_Db_Table_Abstract::DEFINITION] = $tableDefinition;
1619 }
1620
1621 return new $tableName($options);
1622 }
1623
1624 }
1625
-
open/home/peruvian/subdomains/m.peruvianvip.com/vendor/zendframework/zendframework1/library/Zend/Db/Table/Abstract.php
Zend_Db_Table_Abstract->_fetch(Zend_Db_Table_Select)
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 Table
18 * @copyright Copyright (c) 2005-2015 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 /**
24 * @see Zend_Db_Adapter_Abstract
25 */
26 require_once 'Zend/Db/Adapter/Abstract.php';
27
28 /**
29 * @see Zend_Db_Adapter_Abstract
30 */
31 require_once 'Zend/Db/Select.php';
32
33 /**
34 * @see Zend_Db
35 */
36 require_once 'Zend/Db.php';
37
38 /**
39 * Class for SQL table interface.
40 *
41 * @category Zend
42 * @package Zend_Db
43 * @subpackage Table
44 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com)
45 * @license http://framework.zend.com/license/new-bsd New BSD License
46 */
47 abstract class Zend_Db_Table_Abstract
48 {
49
50 const ADAPTER = 'db';
51 const DEFINITION = 'definition';
52 const DEFINITION_CONFIG_NAME = 'definitionConfigName';
53 const SCHEMA = 'schema';
54 const NAME = 'name';
55 const PRIMARY = 'primary';
56 const COLS = 'cols';
57 const METADATA = 'metadata';
58 const METADATA_CACHE = 'metadataCache';
59 const METADATA_CACHE_IN_CLASS = 'metadataCacheInClass';
60 const ROW_CLASS = 'rowClass';
61 const ROWSET_CLASS = 'rowsetClass';
62 const REFERENCE_MAP = 'referenceMap';
63 const DEPENDENT_TABLES = 'dependentTables';
64 const SEQUENCE = 'sequence';
65
66 const COLUMNS = 'columns';
67 const REF_TABLE_CLASS = 'refTableClass';
68 const REF_COLUMNS = 'refColumns';
69 const ON_DELETE = 'onDelete';
70 const ON_UPDATE = 'onUpdate';
71
72 const CASCADE = 'cascade';
73 const CASCADE_RECURSE = 'cascadeRecurse';
74 const RESTRICT = 'restrict';
75 const SET_NULL = 'setNull';
76
77 const DEFAULT_NONE = 'defaultNone';
78 const DEFAULT_CLASS = 'defaultClass';
79 const DEFAULT_DB = 'defaultDb';
80
81 const SELECT_WITH_FROM_PART = true;
82 const SELECT_WITHOUT_FROM_PART = false;
83
84 /**
85 * Default Zend_Db_Adapter_Abstract object.
86 *
87 * @var Zend_Db_Adapter_Abstract
88 */
89 protected static $_defaultDb;
90
91 /**
92 * Optional Zend_Db_Table_Definition object
93 *
94 * @var unknown_type
95 */
96 protected $_definition = null;
97
98 /**
99 * Optional definition config name used in concrete implementation
100 *
101 * @var string
102 */
103 protected $_definitionConfigName = null;
104
105 /**
106 * Default cache for information provided by the adapter's describeTable() method.
107 *
108 * @var Zend_Cache_Core
109 */
110 protected static $_defaultMetadataCache = null;
111
112 /**
113 * Zend_Db_Adapter_Abstract object.
114 *
115 * @var Zend_Db_Adapter_Abstract
116 */
117 protected $_db;
118
119 /**
120 * The schema name (default null means current schema)
121 *
122 * @var array
123 */
124 protected $_schema = null;
125
126 /**
127 * The table name.
128 *
129 * @var string
130 */
131 protected $_name = null;
132
133 /**
134 * The table column names derived from Zend_Db_Adapter_Abstract::describeTable().
135 *
136 * @var array
137 */
138 protected $_cols;
139
140 /**
141 * The primary key column or columns.
142 * A compound key should be declared as an array.
143 * You may declare a single-column primary key
144 * as a string.
145 *
146 * @var mixed
147 */
148 protected $_primary = null;
149
150 /**
151 * If your primary key is a compound key, and one of the columns uses
152 * an auto-increment or sequence-generated value, set _identity
153 * to the ordinal index in the $_primary array for that column.
154 * Note this index is the position of the column in the primary key,
155 * not the position of the column in the table. The primary key
156 * array is 1-based.
157 *
158 * @var integer
159 */
160 protected $_identity = 1;
161
162 /**
163 * Define the logic for new values in the primary key.
164 * May be a string, boolean true, or boolean false.
165 *
166 * @var mixed
167 */
168 protected $_sequence = true;
169
170 /**
171 * Information provided by the adapter's describeTable() method.
172 *
173 * @var array
174 */
175 protected $_metadata = array();
176
177 /**
178 * Cache for information provided by the adapter's describeTable() method.
179 *
180 * @var Zend_Cache_Core
181 */
182 protected $_metadataCache = null;
183
184 /**
185 * Flag: whether or not to cache metadata in the class
186 * @var bool
187 */
188 protected $_metadataCacheInClass = true;
189
190 /**
191 * Classname for row
192 *
193 * @var string
194 */
195 protected $_rowClass = 'Zend_Db_Table_Row';
196
197 /**
198 * Classname for rowset
199 *
200 * @var string
201 */
202 protected $_rowsetClass = 'Zend_Db_Table_Rowset';
203
204 /**
205 * Associative array map of declarative referential integrity rules.
206 * This array has one entry per foreign key in the current table.
207 * Each key is a mnemonic name for one reference rule.
208 *
209 * Each value is also an associative array, with the following keys:
210 * - columns = array of names of column(s) in the child table.
211 * - refTableClass = class name of the parent table.
212 * - refColumns = array of names of column(s) in the parent table,
213 * in the same order as those in the 'columns' entry.
214 * - onDelete = "cascade" means that a delete in the parent table also
215 * causes a delete of referencing rows in the child table.
216 * - onUpdate = "cascade" means that an update of primary key values in
217 * the parent table also causes an update of referencing
218 * rows in the child table.
219 *
220 * @var array
221 */
222 protected $_referenceMap = array();
223
224 /**
225 * Simple array of class names of tables that are "children" of the current
226 * table, in other words tables that contain a foreign key to this one.
227 * Array elements are not table names; they are class names of classes that
228 * extend Zend_Db_Table_Abstract.
229 *
230 * @var array
231 */
232 protected $_dependentTables = array();
233
234
235 protected $_defaultSource = self::DEFAULT_NONE;
236 protected $_defaultValues = array();
237
238 /**
239 * Constructor.
240 *
241 * Supported params for $config are:
242 * - db = user-supplied instance of database connector,
243 * or key name of registry instance.
244 * - name = table name.
245 * - primary = string or array of primary key(s).
246 * - rowClass = row class name.
247 * - rowsetClass = rowset class name.
248 * - referenceMap = array structure to declare relationship
249 * to parent tables.
250 * - dependentTables = array of child tables.
251 * - metadataCache = cache for information from adapter describeTable().
252 *
253 * @param mixed $config Array of user-specified config options, or just the Db Adapter.
254 * @return void
255 */
256 public function __construct($config = array())
257 {
258 /**
259 * Allow a scalar argument to be the Adapter object or Registry key.
260 */
261 if (!is_array($config)) {
262 $config = array(self::ADAPTER => $config);
263 }
264
265 if ($config) {
266 $this->setOptions($config);
267 }
268
269 $this->_setup();
270 $this->init();
271 }
272
273 /**
274 * setOptions()
275 *
276 * @param array $options
277 * @return Zend_Db_Table_Abstract
278 */
279 public function setOptions(Array $options)
280 {
281 foreach ($options as $key => $value) {
282 switch ($key) {
283 case self::ADAPTER:
284 $this->_setAdapter($value);
285 break;
286 case self::DEFINITION:
287 $this->setDefinition($value);
288 break;
289 case self::DEFINITION_CONFIG_NAME:
290 $this->setDefinitionConfigName($value);
291 break;
292 case self::SCHEMA:
293 $this->_schema = (string) $value;
294 break;
295 case self::NAME:
296 $this->_name = (string) $value;
297 break;
298 case self::PRIMARY:
299 $this->_primary = (array) $value;
300 break;
301 case self::ROW_CLASS:
302 $this->setRowClass($value);
303 break;
304 case self::ROWSET_CLASS:
305 $this->setRowsetClass($value);
306 break;
307 case self::REFERENCE_MAP:
308 $this->setReferences($value);
309 break;
310 case self::DEPENDENT_TABLES:
311 $this->setDependentTables($value);
312 break;
313 case self::METADATA_CACHE:
314 $this->_setMetadataCache($value);
315 break;
316 case self::METADATA_CACHE_IN_CLASS:
317 $this->setMetadataCacheInClass($value);
318 break;
319 case self::SEQUENCE:
320 $this->_setSequence($value);
321 break;
322 default:
323 // ignore unrecognized configuration directive
324 break;
325 }
326 }
327
328 return $this;
329 }
330
331 /**
332 * setDefinition()
333 *
334 * @param Zend_Db_Table_Definition $definition
335 * @return Zend_Db_Table_Abstract
336 */
337 public function setDefinition(Zend_Db_Table_Definition $definition)
338 {
339 $this->_definition = $definition;
340 return $this;
341 }
342
343 /**
344 * getDefinition()
345 *
346 * @return Zend_Db_Table_Definition|null
347 */
348 public function getDefinition()
349 {
350 return $this->_definition;
351 }
352
353 /**
354 * setDefinitionConfigName()
355 *
356 * @param string $definition
357 * @return Zend_Db_Table_Abstract
358 */
359 public function setDefinitionConfigName($definitionConfigName)
360 {
361 $this->_definitionConfigName = $definitionConfigName;
362 return $this;
363 }
364
365 /**
366 * getDefinitionConfigName()
367 *
368 * @return string
369 */
370 public function getDefinitionConfigName()
371 {
372 return $this->_definitionConfigName;
373 }
374
375 /**
376 * @param string $classname
377 * @return Zend_Db_Table_Abstract Provides a fluent interface
378 */
379 public function setRowClass($classname)
380 {
381 $this->_rowClass = (string) $classname;
382
383 return $this;
384 }
385
386 /**
387 * @return string
388 */
389 public function getRowClass()
390 {
391 return $this->_rowClass;
392 }
393
394 /**
395 * @param string $classname
396 * @return Zend_Db_Table_Abstract Provides a fluent interface
397 */
398 public function setRowsetClass($classname)
399 {
400 $this->_rowsetClass = (string) $classname;
401
402 return $this;
403 }
404
405 /**
406 * @return string
407 */
408 public function getRowsetClass()
409 {
410 return $this->_rowsetClass;
411 }
412
413 /**
414 * Add a reference to the reference map
415 *
416 * @param string $ruleKey
417 * @param string|array $columns
418 * @param string $refTableClass
419 * @param string|array $refColumns
420 * @param string $onDelete
421 * @param string $onUpdate
422 * @return Zend_Db_Table_Abstract
423 */
424 public function addReference($ruleKey, $columns, $refTableClass, $refColumns,
425 $onDelete = null, $onUpdate = null)
426 {
427 $reference = array(self::COLUMNS => (array) $columns,
428 self::REF_TABLE_CLASS => $refTableClass,
429 self::REF_COLUMNS => (array) $refColumns);
430
431 if (!empty($onDelete)) {
432 $reference[self::ON_DELETE] = $onDelete;
433 }
434
435 if (!empty($onUpdate)) {
436 $reference[self::ON_UPDATE] = $onUpdate;
437 }
438
439 $this->_referenceMap[$ruleKey] = $reference;
440
441 return $this;
442 }
443
444 /**
445 * @param array $referenceMap
446 * @return Zend_Db_Table_Abstract Provides a fluent interface
447 */
448 public function setReferences(array $referenceMap)
449 {
450 $this->_referenceMap = $referenceMap;
451
452 return $this;
453 }
454
455 /**
456 * @param string $tableClassname
457 * @param string $ruleKey OPTIONAL
458 * @return array
459 * @throws Zend_Db_Table_Exception
460 */
461 public function getReference($tableClassname, $ruleKey = null)
462 {
463 $thisClass = get_class($this);
464 if ($thisClass === 'Zend_Db_Table') {
465 $thisClass = $this->_definitionConfigName;
466 }
467 $refMap = $this->_getReferenceMapNormalized();
468 if ($ruleKey !== null) {
469 if (!isset($refMap[$ruleKey])) {
470 require_once "Zend/Db/Table/Exception.php";
471 throw new Zend_Db_Table_Exception("No reference rule \"$ruleKey\" from table $thisClass to table $tableClassname");
472 }
473 if ($refMap[$ruleKey][self::REF_TABLE_CLASS] != $tableClassname) {
474 require_once "Zend/Db/Table/Exception.php";
475 throw new Zend_Db_Table_Exception("Reference rule \"$ruleKey\" does not reference table $tableClassname");
476 }
477 return $refMap[$ruleKey];
478 }
479 foreach ($refMap as $reference) {
480 if ($reference[self::REF_TABLE_CLASS] == $tableClassname) {
481 return $reference;
482 }
483 }
484 require_once "Zend/Db/Table/Exception.php";
485 throw new Zend_Db_Table_Exception("No reference from table $thisClass to table $tableClassname");
486 }
487
488 /**
489 * @param array $dependentTables
490 * @return Zend_Db_Table_Abstract Provides a fluent interface
491 */
492 public function setDependentTables(array $dependentTables)
493 {
494 $this->_dependentTables = $dependentTables;
495
496 return $this;
497 }
498
499 /**
500 * @return array
501 */
502 public function getDependentTables()
503 {
504 return $this->_dependentTables;
505 }
506
507 /**
508 * set the defaultSource property - this tells the table class where to find default values
509 *
510 * @param string $defaultSource
511 * @return Zend_Db_Table_Abstract
512 */
513 public function setDefaultSource($defaultSource = self::DEFAULT_NONE)
514 {
515 if (!in_array($defaultSource, array(self::DEFAULT_CLASS, self::DEFAULT_DB, self::DEFAULT_NONE))) {
516 $defaultSource = self::DEFAULT_NONE;
517 }
518
519 $this->_defaultSource = $defaultSource;
520 return $this;
521 }
522
523 /**
524 * returns the default source flag that determines where defaultSources come from
525 *
526 * @return unknown
527 */
528 public function getDefaultSource()
529 {
530 return $this->_defaultSource;
531 }
532
533 /**
534 * set the default values for the table class
535 *
536 * @param array $defaultValues
537 * @return Zend_Db_Table_Abstract
538 */
539 public function setDefaultValues(Array $defaultValues)
540 {
541 foreach ($defaultValues as $defaultName => $defaultValue) {
542 if (array_key_exists($defaultName, $this->_metadata)) {
543