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
      • Reflection
      • Table
    • DI
      • Config
        • Adapters
      • Extensions
    • Diagnostics
    • Forms
      • Controls
      • Rendering
    • Http
    • Iterators
    • Latte
    • Loaders
    • Localization
    • Mail
    • Neon
    • PhpGenerator
    • Reflection
    • Security
    • Templating
    • Utils
  • NetteModule
  • none
  • Tracy
    • Bridges
      • Nette

Classes

  • Connection
  • Context
  • Helpers
  • ResultSet
  • Row
  • SqlLiteral
  • SqlPreprocessor
  • Structure

Interfaces

  • IConventions
  • IReflection
  • IRow
  • IRowContainer
  • IStructure
  • ISupplementalDriver

Exceptions

  • ConnectionException
  • ConstraintViolationException
  • DriverException
  • ForeignKeyConstraintViolationException
  • NotNullConstraintViolationException
  • UniqueConstraintViolationException
  • 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;
  9: 
 10: use Nette;
 11: 
 12: 
 13: /**
 14:  * Cached reflection of database structure.
 15:  */
 16: class Structure extends Nette\Object implements IStructure
 17: {
 18:     /** @var Connection */
 19:     protected $connection;
 20: 
 21:     /** @var Nette\Caching\Cache */
 22:     protected $cache;
 23: 
 24:     /** @var array */
 25:     protected $structure;
 26: 
 27:     /** @var bool */
 28:     protected $isRebuilt = FALSE;
 29: 
 30: 
 31:     public function __construct(Connection $connection, Nette\Caching\IStorage $cacheStorage)
 32:     {
 33:         $this->connection = $connection;
 34:         $this->cache = new Nette\Caching\Cache($cacheStorage, 'Nette.Database.Structure.' . md5($this->connection->getDsn()));
 35:     }
 36: 
 37: 
 38:     public function getTables()
 39:     {
 40:         $this->needStructure();
 41:         return $this->structure['tables'];
 42:     }
 43: 
 44: 
 45:     public function getColumns($table)
 46:     {
 47:         $this->needStructure();
 48:         $table = $this->resolveFQTableName($table);
 49: 
 50:         if (!isset($this->structure['columns'][$table])) {
 51:             throw new Nette\InvalidArgumentException("Table '$table' does not exist.");
 52:         }
 53: 
 54:         return $this->structure['columns'][$table];
 55:     }
 56: 
 57: 
 58:     public function getPrimaryKey($table)
 59:     {
 60:         $this->needStructure();
 61:         $table = $this->resolveFQTableName($table);
 62: 
 63:         if (!isset($this->structure['primary'][$table])) {
 64:             return NULL;
 65:         }
 66: 
 67:         return $this->structure['primary'][$table];
 68:     }
 69: 
 70: 
 71:     public function getPrimaryKeySequence($table)
 72:     {
 73:         $this->needStructure();
 74:         $table = $this->resolveFQTableName($table);
 75: 
 76:         if (!$this->connection->getSupplementalDriver()->isSupported(ISupplementalDriver::SUPPORT_SEQUENCE)) {
 77:             return NULL;
 78:         }
 79: 
 80:         $primary = $this->getPrimaryKey($table);
 81:         if (!$primary || is_array($primary)) {
 82:             return NULL;
 83:         }
 84: 
 85:         foreach ($this->structure['columns'][$table] as $columnMeta) {
 86:             if ($columnMeta['name'] === $primary) {
 87:                 return isset($columnMeta['vendor']['sequence']) ? $columnMeta['vendor']['sequence'] : NULL;
 88:             }
 89:         }
 90: 
 91:         return NULL;
 92:     }
 93: 
 94: 
 95:     public function getHasManyReference($table, $targetTable = NULL)
 96:     {
 97:         $this->needStructure();
 98:         $table = $this->resolveFQTableName($table);
 99: 
100:         if ($targetTable) {
101:             $targetTable = $this->resolveFQTableName($targetTable);
102:             foreach ($this->structure['hasMany'][$table] as $key => $value) {
103:                 if (strtolower($key) === $targetTable) {
104:                     return $this->structure['hasMany'][$table][$key];
105:                 }
106:             }
107: 
108:             return NULL;
109: 
110:         } else {
111:             if (!isset($this->structure['hasMany'][$table])) {
112:                 return array();
113:             }
114:             return $this->structure['hasMany'][$table];
115:         }
116:     }
117: 
118: 
119:     public function getBelongsToReference($table, $column = NULL)
120:     {
121:         $this->needStructure();
122:         $table = $this->resolveFQTableName($table);
123: 
124:         if ($column) {
125:             $column = strtolower($column);
126:             if (!isset($this->structure['belongsTo'][$table][$column])) {
127:                 return NULL;
128:             }
129:             return $this->structure['belongsTo'][$table][$column];
130: 
131:         } else {
132:             if (!isset($this->structure['belongsTo'][$table])) {
133:                 return array();
134:             }
135:             return $this->structure['belongsTo'][$table];
136:         }
137:     }
138: 
139: 
140:     public function rebuild()
141:     {
142:         $this->structure = $this->loadStructure();
143:         $this->cache->save('structure', $this->structure);
144:         $this->isRebuilt = TRUE;
145:     }
146: 
147: 
148:     public function isRebuilt()
149:     {
150:         return $this->isRebuilt;
151:     }
152: 
153: 
154:     protected function needStructure()
155:     {
156:         if ($this->structure !== NULL) {
157:             return;
158:         }
159: 
160:         $this->structure = $this->cache->load('structure', array($this, 'loadStructure'));
161:     }
162: 
163: 
164:     /**
165:      * @internal
166:      */
167:     public function loadStructure()
168:     {
169:         $driver = $this->connection->getSupplementalDriver();
170: 
171:         $structure = array();
172:         $structure['tables'] = $driver->getTables();
173: 
174:         foreach ($structure['tables'] as $tablePair) {
175:             if ($tablePair['view']) {
176:                 continue;
177:             }
178: 
179:             if (isset($tablePair['fullName'])) {
180:                 $table = $tablePair['fullName'];
181:                 $structure['aliases'][strtolower($tablePair['name'])] = strtolower($table);
182:             } else {
183:                 $table = $tablePair['name'];
184:             }
185: 
186:             $structure['columns'][strtolower($table)] = $columns = $driver->getColumns($table);
187:             $structure['primary'][strtolower($table)] = $this->analyzePrimaryKey($columns);
188:             $this->analyzeForeignKeys($structure, $table);
189:         }
190: 
191:         if (isset($structure['hasMany'])) {
192:             foreach ($structure['hasMany'] as & $table) {
193:                 uksort($table, function ($a, $b) {
194:                     return strlen($a) - strlen($b);
195:                 });
196:             }
197:         }
198: 
199:         return $structure;
200:     }
201: 
202: 
203:     protected function analyzePrimaryKey(array $columns)
204:     {
205:         $primary = array();
206:         foreach ($columns as $column) {
207:             if ($column['primary']) {
208:                 $primary[] = $column['name'];
209:             }
210:         }
211: 
212:         if (count($primary) === 0) {
213:             return NULL;
214:         } elseif (count($primary) === 1) {
215:             return reset($primary);
216:         } else {
217:             return $primary;
218:         }
219:     }
220: 
221: 
222:     protected function analyzeForeignKeys(& $structure, $table)
223:     {
224:         foreach ($this->connection->getSupplementalDriver()->getForeignKeys($table) as $row) {
225:             $structure['belongsTo'][strtolower($table)][$row['local']] = $row['table'];
226:             $structure['hasMany'][strtolower($row['table'])][$table][] = $row['local'];
227:         }
228: 
229:         if (isset($structure['belongsTo'][$table])) {
230:             uksort($structure['belongsTo'][$table], function ($a, $b) {
231:                 return strlen($a) - strlen($b);
232:             });
233:         }
234:     }
235: 
236: 
237:     protected function resolveFQTableName($table)
238:     {
239:         $name = strtolower($table);
240:         if (isset($this->structure['columns'][$name])) {
241:             return $name;
242:         }
243: 
244:         if (isset($this->structure['aliases'][$name])) {
245:             return $this->structure['aliases'][$name];
246:         }
247: 
248:         return $name;
249:     }
250: 
251: }
252: 
Nette 2.3.4 API API documentation generated by ApiGen 2.8.0