找到在不同数据库平台之间重用实体注释的解决方案我达到了这一点:
我有一个解决方案,用于在实体类元数据监听 loadClassMetada 事件上重命名 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、regexp 替换和 file_put_contents)...但不喜欢我。
我的问题(最后)是如果可能的话,当 symfony2-doctrine2 生成注释缓存和/或代理类时,设置正确的 tableName?然后我的实体代码保持不变,并且 loadClassMetadata 方法逻辑仅在生成缓存时才被调用。