異なるデータベース プラットフォーム間でエンティティ アノテーションを再利用するためのソリューションを見つけると、次のようになります。
エンティティ クラス メタデータの tableName を名前変更するためのソリューションがあります。
私のservices.xml
<service id="framework.loadclassmetadata.listener" class="%framework.loadclassmetadata.listener.class%">
<tag name="doctrine.event_listener" event="loadClassMetadata" method="loadClassMetadata"/>
<call method="setContainer"><argument type="service" id="service_container" /></call>
</service>
私のリスナークラス:
<?php
namespace Fluency\Bundle\FrameworkBundle\EventListener;
use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Symfony\Component\DependencyInjection\ContainerAware;
/**
* Class LoadClassMetadataListener
*
* @package Fluency\Bundle\FrameworkBundle\EventListener
*/
class LoadClassMetadataListener extends ContainerAware
{
/**
* @param LoadClassMetadataEventArgs $args
*/
public function loadClassMetadata(LoadClassMetadataEventArgs $args)
{
$connection = $this->container->get('database_connection');
$classMetadata = $args->getClassMetadata();
if(!$connection->getDatabasePlatform()->supportsSchemas())
{
$tableName = $classMetadata->table['name'];
$classMetadata->table['name'] = str_replace('.', '_', $tableName);
foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
if ($mapping['type'] == ClassMetadataInfo::MANY_TO_MANY) {
if(isset($classMetadata->associationMappings[$fieldName]['joinTable']['name']))
{
$mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
$classMetadata->associationMappings[$fieldName]['joinTable']['name'] = str_replace('.', '_',
$mappedTableName);
}
}
}
}
}
}
また、postgresql などのデータベース プラットフォームでスキーマを作成するためのソリューション:
<?php
namespace Fluency\Bundle\FrameworkBundle\EventListener;
use Doctrine\DBAL\DBALException;
use Doctrine\DBAL\Event\SchemaCreateTableEventArgs;
use Symfony\Component\DependencyInjection\ContainerAware;
/**
* Class SchemaCreateTableListener
*
* @package Fluency\Bundle\FrameworkBundle\EventListener
*/
class SchemaCreateTableListener extends ContainerAware
{
/**
* @var array
*/
private $_createdSchemas = array();
/**
* @param SchemaCreateTableEventArgs $args
*/
public function onSchemaCreateTable(SchemaCreateTableEventArgs $args)
{
$connection = $this->container->get('database_connection');
if ($args->getPlatform()->supportsSchemas())
{
$tableName = $args->getTable()->getName();
$separetedTableName = explode('.', $tableName);
if (count($separetedTableName) == 2)
{
$schemaName = $separetedTableName[0];
if (!in_array($schemaName, $this->_createdSchemas))
{
try
{
$connection->exec(sprintf("CREATE SCHEMA %s", $schemaName));
}
catch (DBALException $e)
{
}
$this->_createdSchemas[] = $schemaName;
}
}
}
}
}
すべて正常に動作しますが、クラスのメタデータが必要になるたびに、イベントリスナーがメインエンティティと各関連エンティティによって呼び出されるのは最適な原因ではないと思います。私は難しい方法で注釈を変更し、エンティティを読み取り、正規表現を使用してテーブル名を置き換えるコマンドを使用した汚いソリューションを考えました。(file_get_contents、正規表現の置換、および file_put_contents)...しかし、私は好きではありません。
私の質問 (最後に) は、可能であれば、symfony2-doctrine2 が注釈キャッシュやプロキシ クラスを生成するときに、正しい tableName を設定しますか? その後、私のエンティティコードは変更されずに残り、キャッシュが生成されたときにのみ呼び出される loadClassMetadata メソッドロジックが残ります。