diff --git a/src/Propel/Runtime/Map/DatabaseMap.php b/src/Propel/Runtime/Map/DatabaseMap.php index 9ab60c508..5f6cb7ee1 100644 --- a/src/Propel/Runtime/Map/DatabaseMap.php +++ b/src/Propel/Runtime/Map/DatabaseMap.php @@ -54,6 +54,27 @@ class DatabaseMap */ protected $tablesByPhpName = []; + /** + * True if all tables were loaded. + * + * @var bool + */ + protected $areTablesLoaded = false; + + /** + * Holds all registered tables. + * + * @var array> + */ + protected $registeredTables = []; + + /** + * Shows if the table was successfully resolved by its name. + * + * @var array + */ + protected $resolvedTableNames = []; + /** * @param string $name Name of the database. */ @@ -225,7 +246,49 @@ public function registerTableMapClassByName(string $tableName, ?string $tablePhp */ public function registerTableMapClasses(array $tableMapClasses): void { - array_map([$this, 'registerTableMapClass'], $tableMapClasses); + $this->registeredTables = array_unique(array_merge($this->registeredTables, $tableMapClasses)); + } + + /** + * Tries to resolve a table by the name via PHP name class. + * + * @param string $name The String representation of the table. + * + * @return bool if the table was resolved by the name + */ + protected function loadTableMap(string $name): bool + { + if ($this->areTablesLoaded) { + return true; + } + if (isset($this->resolvedTableNames[$name])) { + return $this->resolvedTableNames[$name]; + } + $className = ucfirst(str_replace('_', '', ucwords($name, '_'))); + $className .= 'TableMap'; + $results = array_filter($this->registeredTables, function ($registeredTableName) use ($className) { + return substr($registeredTableName, -strlen($className)) === $className; + }); + + array_map([$this, 'registerTableMapClass'], $results); + $this->resolvedTableNames[$name] = count($results) > 0; + + return $this->resolvedTableNames[$name]; + } + + /** + * Loads all registered tables classes and fills in name and PHP name lookup indices. + * + * @return void + */ + protected function loadTableMaps(): void + { + if ($this->areTablesLoaded) { + return; + } + + array_map([$this, 'registerTableMapClass'], $this->registeredTables); + $this->areTablesLoaded = true; } /** @@ -241,7 +304,11 @@ public function hasTable(string $name): bool $name = substr($name, 0, strpos($name, '.')); } - return isset($this->tables[$name]); + if (isset($this->tables[$name])) { + return true; + } + + return $this->loadTableMap($name) && isset($this->tables[$name]); } /** @@ -256,7 +323,14 @@ public function hasTable(string $name): bool public function getTable(string $name): TableMap { if (!isset($this->tables[$name])) { - throw new TableNotFoundException(sprintf('Cannot fetch TableMap for undefined table `%s` in database `%s`.', $name, $this->getName())); + $this->loadTableMap($name); + if (!isset($this->tables[$name])) { + $this->loadTableMaps(); + } + + if (!isset($this->tables[$name])) { + throw new TableNotFoundException(sprintf('Cannot fetch TableMap for undefined table `%s` in database `%s`.', $name, $this->getName())); + } } $tableOrClass = $this->tables[$name];