Namespaces

  • Latte
    • Loaders
    • Macros
    • Runtime
  • Nette
    • Application
      • Responses
      • Routers
      • UI
    • Bridges
      • ApplicationDI
      • ApplicationLatte
      • ApplicationTracy
      • CacheDI
      • CacheLatte
      • DatabaseDI
      • DatabaseTracy
      • DITracy
      • FormsDI
      • FormsLatte
      • Framework
      • HttpDI
      • HttpTracy
      • MailDI
      • ReflectionDI
      • SecurityDI
      • SecurityTracy
    • Caching
      • Storages
    • ComponentModel
    • Database
      • Conventions
      • Drivers
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
      • Traits
    • Reflection
    • Security
    • Tokenizer
    • Utils
  • Tracy
    • Bridges
      • Nette
  • none

Classes

  • ActiveRow
  • GroupedSelection
  • Selection
  • SqlBuilder

Interfaces

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