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:  * 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:             trigger_error("Exception in " . __METHOD__ . "(): {$e->getMessage()} in {$e->getFile()}:{$e->getLine()}", E_USER_ERROR);
 68:         }
 69:     }
 70: 
 71: 
 72:     /**
 73:      * @return array
 74:      */
 75:     public function toArray()
 76:     {
 77:         $this->accessColumn(NULL);
 78:         return $this->data;
 79:     }
 80: 
 81: 
 82:     /**
 83:      * Returns primary key value.
 84:      * @param  bool
 85:      * @return mixed
 86:      */
 87:     public function getPrimary($need = TRUE)
 88:     {
 89:         $primary = $this->table->getPrimary($need);
 90:         if ($primary === NULL) {
 91:             return NULL;
 92: 
 93:         } elseif (!is_array($primary)) {
 94:             if (isset($this->data[$primary])) {
 95:                 return $this->data[$primary];
 96:             } elseif ($need) {
 97:                 throw new Nette\InvalidStateException("Row does not contain primary $primary column data.");
 98:             } else {
 99:                 return NULL;
100:             }
101: 
102:         } else {
103:             $primaryVal = array();
104:             foreach ($primary as $key) {
105:                 if (!isset($this->data[$key])) {
106:                     if ($need) {
107:                         throw new Nette\InvalidStateException("Row does not contain primary $key column data.");
108:                     } else {
109:                         return NULL;
110:                     }
111:                 }
112:                 $primaryVal[$key] = $this->data[$key];
113:             }
114:             return $primaryVal;
115:         }
116:     }
117: 
118: 
119:     /**
120:      * Returns row signature (composition of primary keys)
121:      * @param  bool
122:      * @return string
123:      */
124:     public function getSignature($need = TRUE)
125:     {
126:         return implode('|', (array) $this->getPrimary($need));
127:     }
128: 
129: 
130:     /**
131:      * Returns referenced row.
132:      * @param  string
133:      * @param  string
134:      * @return ActiveRow or NULL if the row does not exist
135:      */
136:     public function ref($key, $throughColumn = NULL)
137:     {
138:         if (!$throughColumn) {
139:             list($key, $throughColumn) = $this->table->getConnection()->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
140:         }
141: 
142:         return $this->getReference($key, $throughColumn);
143:     }
144: 
145: 
146:     /**
147:      * Returns referencing rows.
148:      * @param  string
149:      * @param  string
150:      * @return GroupedSelection
151:      */
152:     public function related($key, $throughColumn = NULL)
153:     {
154:         if (strpos($key, '.') !== FALSE) {
155:             list($key, $throughColumn) = explode('.', $key);
156:         } elseif (!$throughColumn) {
157:             list($key, $throughColumn) = $this->table->getConnection()->getDatabaseReflection()->getHasManyReference($this->table->getName(), $key);
158:         }
159: 
160:         return $this->table->getReferencingTable($key, $throughColumn, $this[$this->table->getPrimary()]);
161:     }
162: 
163: 
164:     /**
165:      * Updates row.
166:      * @param  array or NULL for all modified values
167:      * @return int number of affected rows or FALSE in case of an error
168:      */
169:     public function update($data = NULL)
170:     {
171:         if ($data instanceof \Traversable) {
172:             $data = iterator_to_array($data);
173:         }
174:         if ($data === NULL) {
175:             $data = $this->modified;
176:         }
177:         return $this->table->getConnection()
178:             ->table($this->table->getName())
179:             ->wherePrimary($this->getPrimary())
180:             ->update($data);
181:     }
182: 
183: 
184:     /**
185:      * Deletes row.
186:      * @return int number of affected rows or FALSE in case of an error
187:      */
188:     public function delete()
189:     {
190:         $res = $this->table->getConnection()
191:             ->table($this->table->getName())
192:             ->wherePrimary($this->getPrimary())
193:             ->delete();
194: 
195:         if ($res > 0 && ($signature = $this->getSignature(FALSE))) {
196:             unset($this->table[$signature]);
197:         }
198: 
199:         return $res;
200:     }
201: 
202: 
203:     /********************* interface IteratorAggregate ****************d*g**/
204: 
205: 
206:     public function getIterator()
207:     {
208:         $this->accessColumn(NULL);
209:         return new \ArrayIterator($this->data);
210:     }
211: 
212: 
213:     /********************* interface ArrayAccess & magic accessors ****************d*g**/
214: 
215: 
216:     /**
217:      * Stores value in column.
218:      * @param  string column name
219:      * @param  string value
220:      * @return void
221:      */
222:     public function offsetSet($key, $value)
223:     {
224:         $this->__set($key, $value);
225:     }
226: 
227: 
228:     /**
229:      * Returns value of column.
230:      * @param  string column name
231:      * @return string
232:      */
233:     public function offsetGet($key)
234:     {
235:         return $this->__get($key);
236:     }
237: 
238: 
239:     /**
240:      * Tests if column exists.
241:      * @param  string column name
242:      * @return bool
243:      */
244:     public function offsetExists($key)
245:     {
246:         return $this->__isset($key);
247:     }
248: 
249: 
250:     /**
251:      * Removes column from data.
252:      * @param  string column name
253:      * @return void
254:      */
255:     public function offsetUnset($key)
256:     {
257:         $this->__unset($key);
258:     }
259: 
260: 
261:     public function __set($key, $value)
262:     {
263:         $this->data[$key] = $value;
264:         $this->modified[$key] = $value;
265:     }
266: 
267: 
268:     public function &__get($key)
269:     {
270:         $this->accessColumn($key);
271:         if (array_key_exists($key, $this->data)) {
272:             return $this->data[$key];
273:         }
274: 
275:         try {
276:             list($table, $column) = $this->table->getConnection()->getDatabaseReflection()->getBelongsToReference($this->table->getName(), $key);
277:             $referenced = $this->getReference($table, $column);
278:             if ($referenced !== FALSE) {
279:                 $this->accessColumn($key, FALSE);
280:                 return $referenced;
281:             }
282:         } catch(MissingReferenceException $e) {}
283: 
284:         $this->removeAccessColumn($key);
285:         throw new Nette\MemberAccessException("Cannot read an undeclared column \"$key\".");
286:     }
287: 
288: 
289:     public function __isset($key)
290:     {
291:         $this->accessColumn($key);
292:         if (array_key_exists($key, $this->data)) {
293:             return isset($this->data[$key]);
294:         }
295:         $this->removeAccessColumn($key);
296:         return FALSE;
297:     }
298: 
299: 
300:     public function __unset($key)
301:     {
302:         unset($this->data[$key]);
303:         unset($this->modified[$key]);
304:     }
305: 
306: 
307:     protected function accessColumn($key, $selectColumn = TRUE)
308:     {
309:         if (isset($this->modified[$key])) {
310:             return;
311:         }
312: 
313:         $this->table->accessColumn($key, $selectColumn);
314:         if ($this->table->getDataRefreshed() && !$this->dataRefreshed) {
315:             $this->data = $this->table[$this->getSignature()]->data;
316:             $this->dataRefreshed = TRUE;
317:         }
318:     }
319: 
320: 
321:     protected function removeAccessColumn($key)
322:     {
323:         $this->table->removeAccessColumn($key);
324:     }
325: 
326: 
327:     protected function getReference($table, $column)
328:     {
329:         $this->accessColumn($column);
330:         if (array_key_exists($column, $this->data)) {
331:             $value = $this->data[$column];
332:             $value = $value instanceof ActiveRow ? $value->getPrimary() : $value;
333: 
334:             $referenced = $this->table->getReferencedTable($table, $column, !empty($this->modified[$column]));
335:             $referenced = isset($referenced[$value]) ? $referenced[$value] : NULL; // referenced row may not exist
336: 
337:             if (!empty($this->modified[$column])) { // cause saving changed column and prevent regenerating referenced table for $column
338:                 $this->modified[$column] = 0; // 0 fails on empty, pass on isset
339:             }
340: 
341:             return $referenced;
342:         }
343: 
344:         return FALSE;
345:     }
346: 
347: }
348: 
Nette Framework 2.0.14 API API documentation generated by ApiGen 2.8.0