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\RowGateway
;
15 use Zend\Db\Sql\TableIdentifier
;
17 abstract class AbstractRowGateway
implements ArrayAccess
, Countable
, RowGatewayInterface
23 protected $isInitialized = false;
26 * @var string|TableIdentifier
28 protected $table = null;
33 protected $primaryKeyColumn = null;
38 protected $primaryKeyData = null;
43 protected $data = array();
48 protected $sql = null;
51 * @var Feature\FeatureSet
53 protected $featureSet = null;
58 public function initialize()
60 if ($this->isInitialized
) {
64 if (!$this->featureSet
instanceof Feature\FeatureSet
) {
65 $this->featureSet
= new Feature\FeatureSet
;
68 $this->featureSet
->setRowGateway($this);
69 $this->featureSet
->apply('preInitialize', array());
71 if (!is_string($this->table
) && !$this->table
instanceof TableIdentifier
) {
72 throw new Exception\
RuntimeException('This row object does not have a valid table set.');
75 if ($this->primaryKeyColumn
== null) {
76 throw new Exception\
RuntimeException('This row object does not have a primary key column set.');
77 } elseif (is_string($this->primaryKeyColumn
)) {
78 $this->primaryKeyColumn
= (array) $this->primaryKeyColumn
;
81 if (!$this->sql
instanceof Sql
) {
82 throw new Exception\
RuntimeException('This row object does not have a Sql object set.');
85 $this->featureSet
->apply('postInitialize', array());
87 $this->isInitialized
= true;
93 * @param array $rowData
94 * @param bool $rowExistsInDatabase
95 * @return AbstractRowGateway
97 public function populate(array $rowData, $rowExistsInDatabase = false)
101 $this->data
= $rowData;
102 if ($rowExistsInDatabase == true) {
103 $this->processPrimaryKeyData();
105 $this->primaryKeyData
= null;
112 * @param mixed $array
115 public function exchangeArray($array)
117 return $this->populate($array, true);
125 public function save()
129 if ($this->rowExistsInDatabase()) {
136 // primary key is always an array even if its a single column
137 foreach ($this->primaryKeyColumn
as $pkColumn) {
138 $where[$pkColumn] = $this->primaryKeyData
[$pkColumn];
139 if ($data[$pkColumn] == $this->primaryKeyData
[$pkColumn]) {
140 unset($data[$pkColumn]);
144 $statement = $this->sql
->prepareStatementForSqlObject($this->sql
->update()->set($data)->where($where));
145 $result = $statement->execute();
146 $rowsAffected = $result->getAffectedRows();
147 unset($statement, $result); // cleanup
152 $insert = $this->sql
->insert();
153 $insert->values($this->data
);
155 $statement = $this->sql
->prepareStatementForSqlObject($insert);
157 $result = $statement->execute();
158 if (($primaryKeyValue = $result->getGeneratedValue()) && count($this->primaryKeyColumn
) == 1) {
159 $this->primaryKeyData
= array($this->primaryKeyColumn
[0] => $primaryKeyValue);
161 // make primary key data available so that $where can be complete
162 $this->processPrimaryKeyData();
164 $rowsAffected = $result->getAffectedRows();
165 unset($statement, $result); // cleanup
168 // primary key is always an array even if its a single column
169 foreach ($this->primaryKeyColumn
as $pkColumn) {
170 $where[$pkColumn] = $this->primaryKeyData
[$pkColumn];
176 $statement = $this->sql
->prepareStatementForSqlObject($this->sql
->select()->where($where));
177 $result = $statement->execute();
178 $rowData = $result->current();
179 unset($statement, $result); // cleanup
181 // make sure data and original data are in sync after save
182 $this->populate($rowData, true);
184 // return rows affected
185 return $rowsAffected;
193 public function delete()
198 // primary key is always an array even if its a single column
199 foreach ($this->primaryKeyColumn
as $pkColumn) {
200 $where[$pkColumn] = $this->primaryKeyData
[$pkColumn];
203 // @todo determine if we need to do a select to ensure 1 row will be affected
205 $statement = $this->sql
->prepareStatementForSqlObject($this->sql
->delete()->where($where));
206 $result = $statement->execute();
208 $affectedRows = $result->getAffectedRows();
209 if ($affectedRows == 1) {
210 // detach from database
211 $this->primaryKeyData
= null;
214 return $affectedRows;
220 * @param string $offset
223 public function offsetExists($offset)
225 return array_key_exists($offset, $this->data
);
231 * @param string $offset
234 public function offsetGet($offset)
236 return $this->data
[$offset];
242 * @param string $offset
243 * @param mixed $value
246 public function offsetSet($offset, $value)
248 $this->data
[$offset] = $value;
255 * @param string $offset
256 * @return AbstractRowGateway
258 public function offsetUnset($offset)
260 $this->data
[$offset] = null;
267 public function count()
269 return count($this->data
);
277 public function toArray()
285 * @param string $name
286 * @throws Exception\InvalidArgumentException
289 public function __get($name)
291 if (array_key_exists($name, $this->data
)) {
292 return $this->data
[$name];
294 throw new Exception\
InvalidArgumentException('Not a valid column in this row: ' . $name);
301 * @param string $name
302 * @param mixed $value
305 public function __set($name, $value)
307 $this->offsetSet($name, $value);
313 * @param string $name
316 public function __isset($name)
318 return $this->offsetExists($name);
324 * @param string $name
327 public function __unset($name)
329 $this->offsetUnset($name);
335 public function rowExistsInDatabase()
337 return ($this->primaryKeyData
!== null);
341 * @throws Exception\RuntimeException
343 protected function processPrimaryKeyData()
345 $this->primaryKeyData
= array();
346 foreach ($this->primaryKeyColumn
as $column) {
347 if (!isset($this->data
[$column])) {
348 throw new Exception\
RuntimeException('While processing primary key data, a known key ' . $column . ' was not found in the data array');
350 $this->primaryKeyData
[$column] = $this->data
[$column];