Namespaces

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

Classes

  • ActiveRow
  • GroupedSelection
  • Selection
  • SqlBuilder

Interfaces

  • IRow
  • IRowContainer
  • 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 (https://davidgrudl.com)
  6:  */
  7: 
  8: namespace Nette\Database\Table;
  9: 
 10: use Nette;
 11: use 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:  * @author     Jan Skrasek
 20:  */
 21: class ActiveRow implements \IteratorAggregate, IRow
 22: {
 23:     /** @var Selection */
 24:     private $table;
 25: 
 26:     /** @var array of row data */
 27:     private $data;
 28: 
 29:     /** @var bool */
 30:     private $dataRefreshed = FALSE;
 31: 
 32: 
 33:     public function __construct(array $data, Selection $table)
 34:     {
 35:         $this->data = $data;
 36:         $this->table = $table;
 37:     }
 38: 
 39: 
 40:     /**
 41:      * @internal
 42:      * @ignore
 43:      */
 44:     public function setTable(Selection $table)
 45:     {
 46:         $this->table = $table;
 47:     }
 48: 
 49: 
 50:     /**
 51:      * @internal
 52:      */
 53:     public function getTable()
 54:     {
 55:         return $this->table;
 56:     }
 57: 
 58: 
 59:     public function __toString()
 60:     {
 61:         try {
 62:             return (string) $this->getPrimary();
 63:         } catch (\Throwable $e) {
 64:         } catch (\Exception $e) {
 65:         }
 66:         if (isset($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 possible int, string, array, object (Nette\DateTime)
 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 IRow 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->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->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|\Traversable (column => value)
170:      * @return bool
171:      */
172:     public function update($data)
173:     {
174:         $selection = $this->table->createSelectionInstance()
175:             ->wherePrimary($this->getPrimary());
176: 
177:         if ($selection->update($data)) {
178:             $selection->select('*');
179:             if (($row = $selection->fetch()) === FALSE) {
180:                 throw new Nette\InvalidStateException('Database refetch failed; row does not exist!');
181:             }
182:             $this->data = $row->data;
183:             return TRUE;
184:         } else {
185:             return FALSE;
186:         }
187:     }
188: 
189: 
190:     /**
191:      * Deletes row.
192:      * @return int number of affected rows
193:      */
194:     public function delete()
195:     {
196:         $res = $this->table->createSelectionInstance()
197:             ->wherePrimary($this->getPrimary())
198:             ->delete();
199: 
200:         if ($res > 0 && ($signature = $this->getSignature(FALSE))) {
201:             unset($this->table[$signature]);
202:         }
203: 
204:         return $res;
205:     }
206: 
207: 
208:     /********************* interface IteratorAggregate ****************d*g**/
209: 
210: 
211:     public function getIterator()
212:     {
213:         $this->accessColumn(NULL);
214:         return new \ArrayIterator($this->data);
215:     }
216: 
217: 
218:     /********************* interface ArrayAccess & magic accessors ****************d*g**/
219: 
220: 
221:     /**
222:      * Stores value in column.
223:      * @param  string column name
224:      * @param  string value
225:      * @return void
226:      */
227:     public function offsetSet($key, $value)
228:     {
229:         $this->__set($key, $value);
230:     }
231: 
232: 
233:     /**
234:      * Returns value of column.
235:      * @param  string column name
236:      * @return string
237:      */
238:     public function offsetGet($key)
239:     {
240:         return $this->__get($key);
241:     }
242: 
243: 
244:     /**
245:      * Tests if column exists.
246:      * @param  string column name
247:      * @return bool
248:      */
249:     public function offsetExists($key)
250:     {
251:         return $this->__isset($key);
252:     }
253: 
254: 
255:     /**
256:      * Removes column from data.
257:      * @param  string column name
258:      * @return void
259:      */
260:     public function offsetUnset($key)
261:     {
262:         $this->__unset($key);
263:     }
264: 
265: 
266:     public function __set($key, $value)
267:     {
268:         throw new Nette\DeprecatedException('ActiveRow is read-only; use update() method instead.');
269:     }
270: 
271: 
272:     public function &__get($key)
273:     {
274:         $this->accessColumn($key);
275:         if (array_key_exists($key, $this->data)) {
276:             return $this->data[$key];
277:         }
278: 
279:         try {
280:             list($table, $column) = $this->table->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
281:             $referenced = $this->getReference($table, $column);
282:             if ($referenced !== FALSE) {
283:                 $this->accessColumn($key, FALSE);
284:                 return $referenced;
285:             }
286:         } catch(MissingReferenceException $e) {}
287: 
288:         $this->removeAccessColumn($key);
289:         throw new Nette\MemberAccessException("Cannot read an undeclared column '$key'.");
290:     }
291: 
292: 
293:     public function __isset($key)
294:     {
295:         $this->accessColumn($key);
296:         if (array_key_exists($key, $this->data)) {
297:             return isset($this->data[$key]);
298:         }
299:         $this->removeAccessColumn($key);
300:         return FALSE;
301:     }
302: 
303: 
304:     public function __unset($key)
305:     {
306:         throw new Nette\DeprecatedException('ActiveRow is read-only.');
307:     }
308: 
309: 
310:     protected function accessColumn($key, $selectColumn = TRUE)
311:     {
312:         $this->table->accessColumn($key, $selectColumn);
313:         if ($this->table->getDataRefreshed() && !$this->dataRefreshed) {
314:             $this->data = $this->table[$this->getSignature()]->data;
315:             $this->dataRefreshed = TRUE;
316:         }
317:     }
318: 
319: 
320:     protected function removeAccessColumn($key)
321:     {
322:         $this->table->removeAccessColumn($key);
323:     }
324: 
325: 
326:     protected function getReference($table, $column)
327:     {
328:         $this->accessColumn($column);
329:         if (array_key_exists($column, $this->data)) {
330:             $value = $this->data[$column];
331:             $referenced = $this->table->getReferencedTable($table, $column, $value);
332:             return isset($referenced[$value]) ? $referenced[$value] : NULL; // referenced row may not exist
333:         }
334: 
335:         return FALSE;
336:     }
337: 
338: }
339: 
Nette 2.1 API documentation generated by ApiGen 2.8.0