在Doctrine2中以编程方式修改表的模式名称?

Adr*_*ter 5 php symfony doctrine-orm

我希望在运行时尽可能使用表名修改表的模式/数据库名称,但ClassMetadataInfo该类似乎没有公开接口来获取/设置此属性.

如果绝对必要,我可以在运行时修改表名,但由于我们必须存储在单个模式/数据库中的表的数量,它不是一个理想的解决方案.

有没有办法实现我想做的事情?提前致谢.

注意:我需要能够在基于注释的实体映射中使用模式占位符来提供完全限定的表名(例如__schema_placeholder__.table_name,对于跨数据库连接).在运行时,我想从__schema_placeholder__.table_name=> 动态重新映射实体 real_schema_name.table_name.

Nic*_*ich 28

您可以通过与侦听器/订阅者挂钩到doctrine事件系统来动态调整表名(和映射).

即"loadClassMetadata"是您可以创建监听器/订阅者的教条事件之一,如教程文章如何注册事件监听器和订阅者中所述.

config.yml

services:
    mapping.listener:
        class: Acme\YourBundle\EventListener\MappingListener
        tags:
            - { name: doctrine.event_listener, event: loadClassMetadata }
Run Code Online (Sandbox Code Playgroud)

MappingListener

use Doctrine\ORM\Event\LoadClassMetadataEventArgs;

class MappingListener
{
    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $classMetadata = $eventArgs->getClassMetadata();
        $table = $classMetadata->table;

        $oldName = $table['name'];      // ... or $classMetaData->getTableName()

        // your logic here ...

        $table['name'] = 'new_table_name';

        $classMetadata->setPrimaryTable($table);

        // ... or add a field-mapping like this

        $fieldMapping = array(
          'fieldName' => 'about',
          'type' => 'string',
           'length' => 255
        );
        $classMetadata->mapField($fieldMapping);
Run Code Online (Sandbox Code Playgroud)

ClassMetadata扩展了ClassMetadataInfo并提供了一个公共变量" table "(包含您的注释或yml提供的映射信息),您可以修改它们!

public table变量是一个包含以下条目的数组:

  • name =>
  • schema =>
  • indices => array
  • uniqueConstraints => array

您可以在保存/更新之前动态注册控制器中的事件侦听器/订户.

$mappingListener = new MappingListener();

// ... maybe even modify the listener using reflection

$evm = $this->get('doctrine')->getManager()->->getEventManager();
$evm->addEventListener('loadClassMetadata', $mappingListener);
Run Code Online (Sandbox Code Playgroud)

此外,您可以引入多个数据库连接/名称并在应用程序中访问它们.

应用程序/配置/ config.yml

doctrine:
    dbal:
        default_connection:   default
        connections:
            default:
                driver:   "%database_driver%"
                host:     "%database_host%"
                port:     "%database_port%"
                dbname:   "%database_name%"
                user:     "%database_user%"
                password: "%database_password%"
                charset:  UTF8
            customer:
                driver:   "%database_driver2%"
                host:     "%database_host2%"
                port:     "%database_port2%"
                dbname:   "%database_name2%"
                user:     "%database_user2%"
                password: "%database_password2%"
                charset:  UTF8
Run Code Online (Sandbox Code Playgroud)

然后让不同的实体经理使用......

  $em = $this->get('doctrine')->getManager('default');
  $em2 = $this->get('doctrine')->getManager('customer');
Run Code Online (Sandbox Code Playgroud)

或存储库

$customers = $this->get('doctrine')
    ->getRepository('AcmeCustomerBundle:Customer', 'customer')
    ->findAll()
;
Run Code Online (Sandbox Code Playgroud)

...或动态添加连接

$this->get('doctrine')
  ->connection('mysql://username:password@localhost/test', 'dynamic_connection');
Run Code Online (Sandbox Code Playgroud)

在烹饪手册章节如何使用多个实体管理器和连接中阅读有关该主题的更多信息.