3 * Zend Framework (http://framework.zend.com/)
5 * @link http://github.com/zendframework/zf2 for the canonical source repository
6 * @copyright Copyright (c) 2005-2013 Zend Technologies USA Inc. (http://www.zend.com)
7 * @license http://framework.zend.com/license/new-bsd New BSD License
10 namespace Zend\Db\TableGateway
;
12 use Zend\Db\Adapter\AdapterInterface
;
13 use Zend\Db\ResultSet\ResultSet
;
14 use Zend\Db\ResultSet\ResultSetInterface
;
15 use Zend\Db\Sql\Delete
;
16 use Zend\Db\Sql\Insert
;
17 use Zend\Db\Sql\Select
;
19 use Zend\Db\Sql\TableIdentifier
;
20 use Zend\Db\Sql\Update
;
21 use Zend\Db\Sql\Where
;
25 * @property AdapterInterface $adapter
26 * @property int $lastInsertValue
27 * @property string $table
29 abstract class AbstractTableGateway
implements TableGatewayInterface
35 protected $isInitialized = false;
38 * @var AdapterInterface
40 protected $adapter = null;
45 protected $table = null;
50 protected $columns = array();
53 * @var Feature\FeatureSet
55 protected $featureSet = null;
58 * @var ResultSetInterface
60 protected $resultSetPrototype = null;
65 protected $sql = null;
71 protected $lastInsertValue = null;
76 public function isInitialized()
78 return $this->isInitialized
;
84 * @throws Exception\RuntimeException
87 public function initialize()
89 if ($this->isInitialized
) {
93 if (!$this->featureSet
instanceof Feature\FeatureSet
) {
94 $this->featureSet
= new Feature\FeatureSet
;
97 $this->featureSet
->setTableGateway($this);
98 $this->featureSet
->apply('preInitialize', array());
100 if (!$this->adapter
instanceof AdapterInterface
) {
101 throw new Exception\
RuntimeException('This table does not have an Adapter setup');
104 if (!is_string($this->table
) && !$this->table
instanceof TableIdentifier
) {
105 throw new Exception\
RuntimeException('This table object does not have a valid table set.');
108 if (!$this->resultSetPrototype
instanceof ResultSetInterface
) {
109 $this->resultSetPrototype
= new ResultSet
;
112 if (!$this->sql
instanceof Sql
) {
113 $this->sql
= new Sql($this->adapter
, $this->table
);
116 $this->featureSet
->apply('postInitialize', array());
118 $this->isInitialized
= true;
126 public function getTable()
134 * @return AdapterInterface
136 public function getAdapter()
138 return $this->adapter
;
144 public function getColumns()
146 return $this->columns
;
150 * @return Feature\FeatureSet
152 public function getFeatureSet()
154 return $this->featureSet
;
158 * Get select result prototype
162 public function getResultSetPrototype()
164 return $this->resultSetPrototype
;
170 public function getSql()
178 * @param Where|\Closure|string|array $where
181 public function select($where = null)
183 if (!$this->isInitialized
) {
187 $select = $this->sql
->select();
189 if ($where instanceof \Closure
) {
191 } elseif ($where !== null) {
192 $select->where($where);
195 return $this->selectWith($select);
199 * @param Select $select
200 * @return null|ResultSetInterface
201 * @throws \RuntimeException
203 public function selectWith(Select
$select)
205 if (!$this->isInitialized
) {
208 return $this->executeSelect($select);
212 * @param Select $select
214 * @throws Exception\RuntimeException
216 protected function executeSelect(Select
$select)
218 $selectState = $select->getRawState();
219 if ($selectState['table'] != $this->table
) {
220 throw new Exception\
RuntimeException('The table name of the provided select object must match that of the table');
223 if ($selectState['columns'] == array(Select
::SQL_STAR
)
224 && $this->columns
!== array()) {
225 $select->columns($this->columns
);
228 // apply preSelect features
229 $this->featureSet
->apply('preSelect', array($select));
231 // prepare and execute
232 $statement = $this->sql
->prepareStatementForSqlObject($select);
233 $result = $statement->execute();
236 $resultSet = clone $this->resultSetPrototype
;
237 $resultSet->initialize($result);
239 // apply postSelect features
240 $this->featureSet
->apply('postSelect', array($statement, $result, $resultSet));
251 public function insert($set)
253 if (!$this->isInitialized
) {
256 $insert = $this->sql
->insert();
257 $insert->values($set);
258 return $this->executeInsert($insert);
262 * @param Insert $insert
265 public function insertWith(Insert
$insert)
267 if (!$this->isInitialized
) {
270 return $this->executeInsert($insert);
274 * @todo add $columns support
276 * @param Insert $insert
278 * @throws Exception\RuntimeException
280 protected function executeInsert(Insert
$insert)
282 $insertState = $insert->getRawState();
283 if ($insertState['table'] != $this->table
) {
284 throw new Exception\
RuntimeException('The table name of the provided Insert object must match that of the table');
287 // apply preInsert features
288 $this->featureSet
->apply('preInsert', array($insert));
290 $statement = $this->sql
->prepareStatementForSqlObject($insert);
291 $result = $statement->execute();
292 $this->lastInsertValue
= $this->adapter
->getDriver()->getConnection()->getLastGeneratedValue();
294 // apply postInsert features
295 $this->featureSet
->apply('postInsert', array($statement, $result));
297 return $result->getAffectedRows();
304 * @param string|array|closure $where
307 public function update($set, $where = null)
309 if (!$this->isInitialized
) {
313 $update = $sql->update();
315 if ($where !== null) {
316 $update->where($where);
318 return $this->executeUpdate($update);
322 * @param \Zend\Db\Sql\Update $update
325 public function updateWith(Update
$update)
327 if (!$this->isInitialized
) {
330 return $this->executeUpdate($update);
334 * @todo add $columns support
336 * @param Update $update
338 * @throws Exception\RuntimeException
340 protected function executeUpdate(Update
$update)
342 $updateState = $update->getRawState();
343 if ($updateState['table'] != $this->table
) {
344 throw new Exception\
RuntimeException('The table name of the provided Update object must match that of the table');
347 // apply preUpdate features
348 $this->featureSet
->apply('preUpdate', array($update));
350 $statement = $this->sql
->prepareStatementForSqlObject($update);
351 $result = $statement->execute();
353 // apply postUpdate features
354 $this->featureSet
->apply('postUpdate', array($statement, $result));
356 return $result->getAffectedRows();
362 * @param Where|\Closure|string|array $where
365 public function delete($where)
367 if (!$this->isInitialized
) {
370 $delete = $this->sql
->delete();
371 if ($where instanceof \Closure
) {
374 $delete->where($where);
376 return $this->executeDelete($delete);
380 * @param Delete $delete
383 public function deleteWith(Delete
$delete)
386 return $this->executeDelete($delete);
390 * @todo add $columns support
392 * @param Delete $delete
394 * @throws Exception\RuntimeException
396 protected function executeDelete(Delete
$delete)
398 $deleteState = $delete->getRawState();
399 if ($deleteState['table'] != $this->table
) {
400 throw new Exception\
RuntimeException('The table name of the provided Update object must match that of the table');
404 $this->featureSet
->apply('preDelete', array($delete));
406 $statement = $this->sql
->prepareStatementForSqlObject($delete);
407 $result = $statement->execute();
409 // apply postDelete features
410 $this->featureSet
->apply('postDelete', array($statement, $result));
412 return $result->getAffectedRows();
416 * Get last insert value
420 public function getLastInsertValue()
422 return $this->lastInsertValue
;
428 * @param string $property
429 * @throws Exception\InvalidArgumentException
432 public function __get($property)
434 switch (strtolower($property)) {
435 case 'lastinsertvalue':
436 return $this->lastInsertValue
;
438 return $this->adapter
;
442 if ($this->featureSet
->canCallMagicGet($property)) {
443 return $this->featureSet
->callMagicGet($property);
445 throw new Exception\
InvalidArgumentException('Invalid magic property access in ' . __CLASS__
. '::__get()');
449 * @param string $property
450 * @param mixed $value
452 * @throws Exception\InvalidArgumentException
454 public function __set($property, $value)
456 if ($this->featureSet
->canCallMagicSet($property)) {
457 return $this->featureSet
->callMagicSet($property, $value);
459 throw new Exception\
InvalidArgumentException('Invalid magic property access in ' . __CLASS__
. '::__set()');
466 * @throws Exception\InvalidArgumentException
468 public function __call($method, $arguments)
470 if ($this->featureSet
->canCallMagicCall($method)) {
471 return $this->featureSet
->callMagicCall($method, $arguments);
473 throw new Exception\
InvalidArgumentException('Invalid method (' . $method . ') called, caught by ' . __CLASS__
. '::__call()');
479 public function __clone()
481 $this->resultSetPrototype
= (isset($this->resultSetPrototype
)) ?
clone $this->resultSetPrototype
: null;
482 $this->sql
= clone $this->sql
;
483 if (is_object($this->table
)) {
484 $this->table
= clone $this->table
;