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
  • PHP

Classes

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