Namespaces

  • Nette
    • Application
      • Diagnostics
      • Responses
      • Routers
      • UI
    • Caching
      • Storages
    • ComponentModel
    • Config
      • Adapters
      • Extensions
    • Database
      • Diagnostics
      • Drivers
      • Reflection
      • Table
    • DI
      • Diagnostics
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
      • Macros
    • Loaders
    • Localization
    • Mail
    • Reflection
    • Security
      • Diagnostics
    • Templating
    • Utils
      • PhpGenerator
  • NetteModule
  • none

Classes

  • ActiveRow
  • GroupedSelection
  • Selection
  • SqlBuilder
  • Overview
  • Namespace
  • Class
  • Tree
  • Deprecated
  • Other releases
  • Nette homepage
  1: <?php
  2: 
  3: /**
  4:  * This file is part of the Nette Framework (https://nette.org)
  5:  * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Database\Table;
  9: 
 10: use Nette,
 11:     Nette\Database\Reflection\MissingReferenceException;
 12: 
 13: 
 14: /**
 15:  * Single row representation.
 16:  * ActiveRow is based on the great library NotORM http://www.notorm.com written by Jakub Vrana.
 17:  *
 18:  * @author     Jakub Vrana
 19:  */
 20: class ActiveRow extends Nette\Object implements \IteratorAggregate, \ArrayAccess
 21: {
 22:     /** @var Selection */
 23:     private $table;
 24: 
 25:     /** @var array of row data */
 26:     private $data;
 27: 
 28:     /** @var bool */
 29:     private $dataRefreshed = FALSE;
 30: 
 31:     /** @var array of new values {@see ActiveRow::update()} */
 32:     private $modified = array();
 33: 
 34: 
 35:     public function __construct(array $data, Selection $table)
 36:     {
 37:         $this->data = $data;
 38:         $this->table = $table;
 39:     }
 40: 
 41: 
 42:     /**
 43:      * @internal
 44:      * @ignore
 45:      */
 46:     public function setTable(Selection $table)
 47:     {
 48:         $this->table = $table;
 49:     }
 50: 
 51: 
 52:     /**
 53:      * @internal
 54:      * @ignore
 55:      */
 56:     public function getTable()
 57:     {
 58:         return $this->table;
 59:     }
 60: 
 61: 
 62:     public function __toString()
 63:     {
 64:         try {
 65:             return (string) $this->getPrimary();
 66:         } catch (\Exception $e) {
 67:             if (func_num_args()) {
 68:                 throw $e;
 69:             }
 70:             trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
 71:         }
 72:     }
 73: 
 74: 
 75:     /**
 76:      * @return array
 77:      */
 78:     public function toArray()
 79:     {
 80:         $this->accessColumn(NULL);
 81:         return $this->data;
 82:     }
 83: 
 84: 
 85:     /**
 86:      * Returns primary key value.
 87:      * @param  bool
 88:      * @return mixed
 89:      */
 90:     public function getPrimary($need = TRUE)
 91:     {
 92:         $primary = $this->table->getPrimary($need);
 93:         if ($primary === NULL) {
 94:             return NULL;
 95: 
 96:         } elseif (!is_array($primary)) {
 97:             if (isset($this->data[$primary])) {
 98:                 return $this->data[$primary];
 99:             } elseif ($need) {
100:                 throw new Nette\InvalidStateException("Row does not contain primary $primary column data.");
101:             } else {
102:                 return NULL;
103:             }
104: 
105:         } else {
106:             $primaryVal = array();
107:             foreach ($primary as $key) {
108:                 if (!isset($this->data[$key])) {
109:                     if ($need) {
110:                         throw new Nette\InvalidStateException("Row does not contain primary $key column data.");
111:                     } else {
112:                         return NULL;
113:                     }
114:                 }
115:                 $primaryVal[$key] = $this->data[$key];
116:             }
117:             return $primaryVal;
118:         }
119:     }
120: 
121: 
122:     /**
123:      * Returns row signature (composition of primary keys)
124:      * @param  bool
125:      * @return string
126:      */
127:     public function getSignature($need = TRUE)
128:     {
129:         return implode('|', (array) $this->getPrimary($need));
130:     }
131: 
132: 
133:     /**
134:      * Returns referenced row.
135:      * @param  string
136:      * @param  string
137:      * @return ActiveRow or NULL if the row does not exist
138:      */
139:     public function ref($key, $throughColumn = NULL)
140:     {
141:         if (!$throughColumn) {
142:             list($key, $throughColumn) = $this->table->getConnection()->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
143:         }
144: 
145:         return $this->getReference($key, $throughColumn);
146:     }
147: 
148: 
149:     /**
150:      * Returns referencing rows.
151:      * @param  string
152:      * @param  string
153:      * @return GroupedSelection
154:      */
155:     public function related($key, $throughColumn = NULL)
156:     {
157:         if (strpos($key, '.') !== FALSE) {
158:             list($key, $throughColumn) = explode('.', $key);
159:         } elseif (!$throughColumn) {
160:             list($key, $throughColumn) = $this->table->getConnection()->getDatabaseReflection()->getHasManyReference($this->table->getName(), $key);
161:         }
162: 
163:         return $this->table->getReferencingTable($key, $throughColumn, $this[$this->table->getPrimary()]);
164:     }
165: 
166: 
167:     /**
168:      * Updates row.
169:      * @param  array or NULL for all modified values
170:      * @return int number of affected rows or FALSE in case of an error
171:      */
172:     public function update($data = NULL)
173:     {
174:         if ($data instanceof \Traversable) {
175:             $data = iterator_to_array($data);
176:         }
177:         if ($data === NULL) {
178:             $data = $this->modified;
179:         }
180:         return $this->table->getConnection()
181:             ->table($this->table->getName())
182:             ->wherePrimary($this->getPrimary())
183:             ->update($data);
184:     }
185: 
186: 
187:     /**
188:      * Deletes row.
189:      * @return int number of affected rows or FALSE in case of an error
190:      */
191:     public function delete()
192:     {
193:         $res = $this->table->getConnection()
194:             ->table($this->table->getName())
195:             ->wherePrimary($this->getPrimary())
196:             ->delete();
197: 
198:         if ($res > 0 && ($signature = $this->getSignature(FALSE))) {
199:             unset($this->table[$signature]);
200:         }
201: 
202:         return $res;
203:     }
204: 
205: 
206:     /********************* interface IteratorAggregate ****************d*g**/
207: 
208: 
209:     public function getIterator()
210:     {
211:         $this->accessColumn(NULL);
212:         return new \ArrayIterator($this->data);
213:     }
214: 
215: 
216:     /********************* interface ArrayAccess & magic accessors ****************d*g**/
217: 
218: 
219:     /**
220:      * Stores value in column.
221:      * @param  string column name
222:      * @param  string value
223:      * @return void
224:      */
225:     public function offsetSet($key, $value)
226:     {
227:         $this->__set($key, $value);
228:     }
229: 
230: 
231:     /**
232:      * Returns value of column.
233:      * @param  string column name
234:      * @return string
235:      */
236:     public function offsetGet($key)
237:     {
238:         return $this->__get($key);
239:     }
240: 
241: 
242:     /**
243:      * Tests if column exists.
244:      * @param  string column name
245:      * @return bool
246:      */
247:     public function offsetExists($key)
248:     {
249:         return $this->__isset($key);
250:     }
251: 
252: 
253:     /**
254:      * Removes column from data.
255:      * @param  string column name
256:      * @return void
257:      */
258:     public function offsetUnset($key)
259:     {
260:         $this->__unset($key);
261:     }
262: 
263: 
264:     public function __set($key, $value)
265:     {
266:         $this->data[$key] = $value;
267:         $this->modified[$key] = $value;
268:     }
269: 
270: 
271:     public function &__get($key)
272:     {
273:         $this->accessColumn($key);
274:         if (array_key_exists($key, $this->data)) {
275:             return $this->data[$key];
276:         }
277: 
278:         try {
279:             list($table, $column) = $this->table->getConnection()->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
280:             $referenced = $this->getReference($table, $column);
281:             if ($referenced !== FALSE) {
282:                 $this->accessColumn($key, FALSE);
283:                 return $referenced;
284:             }
285:         } catch(MissingReferenceException $e) {}
286: 
287:         $this->removeAccessColumn($key);
288:         throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'.");
289:     }
290: 
291: 
292:     public function __isset($key)
293:     {
294:         $this->accessColumn($key);
295:         if (array_key_exists($key, $this->data)) {
296:             return isset($this->data[$key]);
297:         }
298:         $this->removeAccessColumn($key);
299:         return FALSE;
300:     }
301: 
302: 
303:     public function __unset($key)
304:     {
305:         unset($this->data[$key]);
306:         unset($this->modified[$key]);
307:     }
308: 
309: 
310:     protected function accessColumn($key, $selectColumn = TRUE)
311:     {
312:         if (isset($this->modified[$key])) {
313:             return;
314:         }
315: 
316:         $this->table->accessColumn($key, $selectColumn);
317:         if ($this->table->getDataRefreshed() && !$this->dataRefreshed) {
318:             $this->data = $this->table[$this->getSignature()]->data;
319:             $this->dataRefreshed = TRUE;
320:         }
321:     }
322: 
323: 
324:     protected function removeAccessColumn($key)
325:     {
326:         $this->table->removeAccessColumn($key);
327:     }
328: 
329: 
330:     protected function getReference($table, $column)
331:     {
332:         $this->accessColumn($column);
333:         if (array_key_exists($column, $this->data)) {
334:             $value = $this->data[$column];
335:             $value = $value instanceof ActiveRow ? $value->getPrimary() : $value;
336: 
337:             $referenced = $this->table->getReferencedTable($table, $column, !empty($this->modified[$column]));
338:             $referenced = isset($referenced[$value]) ? $referenced[$value] : NULL; // referenced row may not exist
339: 
340:             if (!empty($this->modified[$column])) { // cause saving changed column and prevent regenerating referenced table for $column
341:                 $this->modified[$column] = 0; // 0 fails on empty, pass on isset
342:             }
343: 
344:             return $referenced;
345:         }
346: 
347:         return FALSE;
348:     }
349: 
350: }
351: 
Nette 2.0 API documentation generated by ApiGen 2.8.0