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