-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Closed
Closed
Copy link
Labels
Description
Related to PR.
My current setup consists of one database with the central schema and additional schemas (one per client). Until now, I was able to define entities in the code using the central schema. The rest did not have a defined schema — each client had a different one — and there is a single code repository.
Now, when I run doctrine:schema:validate, I get the following warning:
User Deprecated: Using unqualified names to create or reference objects in a schema that uses qualified names and lacks a default namespace configuration is deprecated.
(Schema.php:254 called by Schema.php:145, [Doctrine PR doctrine/dbal#6677](https://github.com/doctrine/dbal/pull/6677#user-content-unqualified-names), package doctrine/dbal)
- How can I fix this, and is it even possible?
- I understand that the PR fixes problems with SQL Server, but it breaks other configurations. Is there a way to maybe add a parameter that would allow mixing schemas as before?
My config and code:
// doctrine.yaml
doctrine:
dbal:
default_connection: default
connections:
default:
host: '%database_host%'
port: '%database_port%'
dbname: '%database_name%'
user: '%database_user%'
password: '%database_password%'
server_version: '8.0.32'
charset: utf8mb4
use_savepoints: true
schema_manager_factory: App\Component\Doctrine\CustomSchemaManagerFactory
default_table_options:
charset: utf8mb4
collate: utf8mb4_unicode_ci
// services.yaml
services:
App\Component\Doctrine\CustomSchemaManager:
autowire: true
arguments:
- '@doctrine.dbal.default_connection'
tags:
- { name: 'doctrine.dbal.schema_manager', priority: 1 }
App\Component\Doctrine\CustomSchemaManagerFactory:
autowire: true
// CustomSchemaManagerFactory.php
namespace App\Component\Doctrine;
use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Platforms\AbstractMySQLPlatform;
use Doctrine\DBAL\Schema\AbstractSchemaManager;
use Doctrine\DBAL\Schema\DefaultSchemaManagerFactory;
use Doctrine\DBAL\Schema\SchemaManagerFactory;
final readonly class CustomSchemaManagerFactory implements SchemaManagerFactory
{
private SchemaManagerFactory $defaultFactory;
public function __construct()
{
$this->defaultFactory = new DefaultSchemaManagerFactory();
}
public function createSchemaManager(Connection $connection): AbstractSchemaManager
{
$platform = $connection->getDatabasePlatform();
if ($platform instanceof AbstractMySQLPlatform) {
return new CustomSchemaManager($connection, $platform);
}
return $this->defaultFactory->createSchemaManager($connection);
}
}
// CustomSchemaManager.php
namespace App\Component\Doctrine;
use Doctrine\DBAL\Exception;
use Doctrine\DBAL\Exception\DatabaseRequired;
use Doctrine\DBAL\Schema\MySQLSchemaManager;
use Doctrine\DBAL\Schema\Table;
class CustomSchemaManager extends MySQLSchemaManager
{
public function listTables(): array
{
$database = $this->getDatabase(__METHOD__);
$tables = $this->listTablesForDatabase($database);
$centralTables = $this->listTablesForDatabase('central');
/** @var Table $centralTable */
foreach ($centralTables as $centralTable) {
$name = 'central.'.$centralTable->getName();
$tables[$name] = new Table(
$name,
$centralTable->getColumns(),
$centralTable->getIndexes(),
$centralTable->getUniqueConstraints(),
$centralTable->getForeignKeys(),
$centralTable->getOptions(),
);
}
return $tables;
}
private function listTablesForDatabase(string $database): array
{
$tableColumnsByTable = $this->fetchTableColumnsByTable($database);
$indexColumnsByTable = $this->fetchIndexColumnsByTable($database);
$foreignKeyColumnsByTable = $this->fetchForeignKeyColumnsByTable($database);
$tableOptionsByTable = $this->fetchTableOptionsByTable($database);
$filter = $this->connection->getConfiguration()->getSchemaAssetsFilter();
$tables = [];
foreach ($tableColumnsByTable as $tableName => $tableColumns) {
if (!$filter($tableName)) {
continue;
}
$tables[] = new Table(
$tableName,
$this->_getPortableTableColumnList($tableName, $database, $tableColumns),
$this->_getPortableTableIndexesList($indexColumnsByTable[$tableName] ?? [], $tableName),
[],
$this->_getPortableTableForeignKeysList($foreignKeyColumnsByTable[$tableName] ?? []),
$tableOptionsByTable[$tableName] ?? [],
);
}
return $tables;
}
/** @throws Exception */
private function getDatabase(string $methodName): string
{
$database = $this->connection->getDatabase();
if (null === $database) {
throw DatabaseRequired::new($methodName);
}
return $database;
}
}