Navigation Menu

Skip to content

Commit

Permalink
load table maps lazily
Browse files Browse the repository at this point in the history
  • Loading branch information
mringler committed Aug 8, 2022
1 parent 4e59c81 commit 26eea73
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 12 deletions.
4 changes: 4 additions & 0 deletions psalm-baseline.xml
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
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
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>
*/
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>
*/
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 $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 $tableMapClass The name of the table map to add
*
* @return void
*/
public function registerTableMapClass($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
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
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
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);
}
}

0 comments on commit 26eea73

Please sign in to comment.