Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize lazy loading in DatabaseMap #1972

Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
80 changes: 77 additions & 3 deletions src/Propel/Runtime/Map/DatabaseMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -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<int, class-string<\Propel\Runtime\Map\TableMap>>
*/
protected $registeredTables = [];

/**
* Shows if the table was successfully resolved by its name.
*
* @var array<string, bool>
*/
protected $resolvedTableNames = [];

/**
* @param string $name Name of the database.
*/
Expand Down Expand Up @@ -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;
}

/**
Expand All @@ -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]);
}

/**
Expand All @@ -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];
Expand Down
Loading