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

load table maps lazily #1902

Merged
Merged
Show file tree
Hide file tree
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
4 changes: 4 additions & 0 deletions psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,10 @@
<NullArgument occurrences="1">
<code>null</code>
</NullArgument>
<UndefinedConstant occurrences="2">
<code>T_NAME_FULLY_QUALIFIED</code>
<code>T_NAME_QUALIFIED</code>
</UndefinedConstant>
</file>
<file src="src/Propel/Runtime/ActiveQuery/BaseModelCriteria.php">
<UndefinedMethod occurrences="1">
Expand Down
3 changes: 2 additions & 1 deletion src/Propel/Generator/Builder/Om/TableMapBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -203,7 +203,8 @@ protected function addConstants(): string
'className' => $this->getClasspath(),
'dbName' => $this->getDatabase()->getName(),
'tableName' => $this->getTable()->getName(),
'tablePhpName' => $this->getTable()->isAbstract() ? '' : addslashes($this->getStubObjectBuilder()->getFullyQualifiedClassName()),
'tablePhpName' => $this->getTable()->getPhpName(),
'omClassName' => $this->getTable()->isAbstract() ? '' : addslashes($this->getStubObjectBuilder()->getFullyQualifiedClassName()),
'classPath' => $this->getStubObjectBuilder()->getClasspath(),
'nbColumns' => $this->getTable()->getNumColumns(),
'nbLazyLoadColumns' => $this->getTable()->getNumLazyLoadColumns(),
Expand Down
77 changes: 70 additions & 7 deletions src/Propel/Runtime/Map/DatabaseMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,14 @@ class DatabaseMap
/**
* Tables in the database, using table name as key
*
* @var array<\Propel\Runtime\Map\TableMap>
* @var array<\Propel\Runtime\Map\TableMap|class-string<\Propel\Runtime\Map\TableMap>>
*/
protected $tables = [];

/**
* Tables in the database, using table phpName as key
*
* @var array<\Propel\Runtime\Map\TableMap>
* @var array<\Propel\Runtime\Map\TableMap|class-string<\Propel\Runtime\Map\TableMap>>
*/
protected $tablesByPhpName = [];

Expand Down Expand Up @@ -93,15 +93,29 @@ public function addTableObject(TableMap $table): void
$table->setDatabaseMap($this);

$tableName = $table->getName();
if ($tableName && !$this->hasTable($tableName)) {
if ($tableName && (!$this->hasTable($tableName) || is_string($this->tables[$tableName]))) {
$this->tables[$tableName] = $table;
}

$phpName = $table->getClassName();
if ($phpName && $phpName[0] !== '\\') {
$this->addTableByPhpName($phpName, $table);
}

/**
* @param string|null $phpName
* @param \Propel\Runtime\Map\TableMap|class-string<\Propel\Runtime\Map\TableMap> $tableOrClassMap
*
* @return void
*/
protected function addTableByPhpName(?string $phpName, $tableOrClassMap): void
{
if (!$phpName) {
return;
}
if ($phpName[0] !== '\\') {
$phpName = '\\' . $phpName;
}
$this->tablesByPhpName[$phpName] = $table;
$this->tablesByPhpName[$phpName] = $tableOrClassMap;
}

/**
Expand All @@ -120,6 +134,41 @@ public function addTableFromMapClass(string $tableMapClass): TableMap
return $this->getTable($table->getName());
}

/**
* Registers a table map classes (by qualified name) as table belonging
* to this database.
*
* Classes added like this will only be instantiated when accessed
* through {@link DatabaseMap::getTable()},
* {@link DatabaseMap::getTableByPhpName()}, or
* {@link DatabaseMap::getTables()}
*
* @param class-string<\Propel\Runtime\Map\TableMap>|string $tableMapClass The name of the table map to add
*
* @return void
*/
public function registerTableMapClass(string $tableMapClass): void
{
$tableName = $tableMapClass::TABLE_NAME;
$this->tables[$tableName] = $tableMapClass;

$tablePhpName = $tableMapClass::TABLE_PHP_NAME;
$this->addTableByPhpName($tablePhpName, $tableMapClass);
}

/**
* Registers a list of table map classes (by qualified name) as table maps
* belonging to this database.
*
* @param array<class-string> $tableMapClasses
*
* @return void
*/
public function registerTableMapClasses(array $tableMapClasses): void
{
array_map([$this, 'registerTableMapClass'], $tableMapClasses);
}

/**
* Does this database contain this specific table?
*
Expand Down Expand Up @@ -151,16 +200,28 @@ public function getTable(string $name): TableMap
throw new TableNotFoundException(sprintf('Cannot fetch TableMap for undefined table `%s` in database `%s`.', $name, $this->getName()));
}

return $this->tables[$name];
$tableOrClass = $this->tables[$name];

return is_string($tableOrClass) ? $this->addTableFromMapClass($tableOrClass) : $tableOrClass;
}

/**
* Get a TableMap[] of all of the tables in the database.
*
* If tables are registered by class map name, they will be instantiated.
*
* @return array<\Propel\Runtime\Map\TableMap>
*/
public function getTables(): array
{
foreach ($this->tables as $tableOrClassMap) {
if (!is_string($tableOrClassMap)) {
continue;
}
$this->addTableFromMapClass($tableOrClassMap);
}

/** @var array<\Propel\Runtime\Map\TableMap> */
return $this->tables;
}

Expand Down Expand Up @@ -192,7 +253,9 @@ public function getTableByPhpName(string $phpName): TableMap
$phpName = '\\' . $phpName;
}
if (isset($this->tablesByPhpName[$phpName])) {
return $this->tablesByPhpName[$phpName];
$tableOrClassMap = $this->tablesByPhpName[$phpName];

return is_string($tableOrClassMap) ? $this->addTableFromMapClass($tableOrClassMap) : $tableOrClassMap;
}

if (class_exists($tmClass = $phpName . 'TableMap')) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ public function initDatabaseMaps(array $databaseNameToTableMapClassNames = []):

foreach ($databaseNameToTableMapClassNames as $databaseName => $tableMapClassNames) {
$databaseMap = $this->getDatabaseMap($databaseName);
array_map([$databaseMap, 'addTableFromMapClass'], $tableMapClassNames);
$databaseMap->registerTableMapClasses($tableMapClassNames);
}
}

Expand Down
7 changes: 6 additions & 1 deletion templates/Builder/Om/tableMapConstants.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,15 @@
*/
public const TABLE_NAME = '<?php echo $tableName ?>';

/**
* The PHP name of this class (PascalCase)
*/
public const TABLE_PHP_NAME = '<?php echo $tablePhpName ?>';

/**
* The related Propel class for this table
*/
public const OM_CLASS = '<?php echo $tablePhpName ?>';
public const OM_CLASS = '<?php echo $omClassName ?>';

/**
* A class that can be returned by this tableMap
Expand Down
76 changes: 74 additions & 2 deletions tests/Propel/Tests/Runtime/Map/DatabaseMapTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,75 @@ public function testAddTableFromMapClass()
$this->fail('addTableFromMapClass() adds a table from a map class');
}
}

/**
* @return void
*/
public function testRegisterTableByMapClassAddsClassAsString()
{
$databaseMap = new class('dummyDatabase') extends DatabaseMap {
public function getRawTables(){
return $this->tables;
}

public function getRawTablesByPhpName(){
return $this->tablesByPhpName;
}
};

$tableMapClass = BazTableMap::class;
$databaseMap->registerTableMapClass($tableMapClass);

$tableNameToArray = [
BazTableMap::TABLE_NAME => $databaseMap->getRawTables(),
'\\' . BazTableMap::TABLE_PHP_NAME => $databaseMap->getRawTablesByPhpName(),
];

foreach($tableNameToArray as $name => $tables){
$this->assertArrayHasKey($name, $tables);
$this->assertSame($tableMapClass, $tables[$name]);
}
}

/**
* @return void
*/
public function testGetTableResolvesClassNames()
{
$tableMapClass = BazTableMap::class;
$databaseMap = new DatabaseMap('dummy');
$databaseMap->registerTableMapClass($tableMapClass);

$table = $databaseMap->getTable($tableMapClass::TABLE_NAME);
$this->assertInstanceOf($tableMapClass, $table);
}

/**
* @return void
*/
public function testGetPhpTableResolvesClassNames()
{
$tableMapClass = BazTableMap::class;
$databaseMap = new DatabaseMap('dummy');
$databaseMap->registerTableMapClass($tableMapClass);

$table = $databaseMap->getTableByPhpName($tableMapClass::TABLE_PHP_NAME);
$this->assertInstanceOf($tableMapClass, $table);
}

/**
* @return void
*/
public function testGetTablesResolvesClassNames()
{
$tableMapClass = BazTableMap::class;
$databaseMap = new DatabaseMap('dummy');
$databaseMap->registerTableMapClass($tableMapClass);
$tables = $databaseMap->getTables();

$table = $tables[$tableMapClass::TABLE_NAME];
$this->assertInstanceOf($tableMapClass, $table);
}

/**
* @return void
Expand Down Expand Up @@ -187,12 +256,15 @@ public static function getTmap()

class BazTableMap extends TableMap
{
public const TABLE_NAME = 'baz';
public const TABLE_PHP_NAME = 'Baz';

/**
* @return void
*/
public function initialize(): void
{
$this->setName('baz');
$this->setPhpName('Baz');
$this->setName(self::TABLE_NAME);
$this->setPhpName(self::TABLE_PHP_NAME);
}
}