在Doctrine2中以编程方式修改表的架构名称? [英] Programmatically modify table's schema name in Doctrine2?

查看:81
本文介绍了在Doctrine2中以编程方式修改表的架构名称?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想在运行时修改表的架构/数据库名称解决方案

您可以通过挂钩教义的事件之一您可以按照食谱文章如何注册事件侦听器和订阅者.

示例

config.yml

services:
    mapping.listener:
        class: Acme\YourBundle\EventListener\MappingListener
        tags:
            - { name: doctrine.event_listener, event: loadClassMetadata }

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);

ClassMetadata 扩展了ClassMetadataInfo 并提供一个公共变量"

公共表变量是具有以下条目的数组:

  • 名称=>
  • 模式=>
  • indexes =>数组
  • uniqueConstraints =>数组

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

$mappingListener = new MappingListener();

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

$evm = $this->get('doctrine')->getManager()->->getEventManager();
$evm->addEventListener('loadClassMetadata', $mappingListener);


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

app/config/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

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

  $em = $this->get('doctrine')->getManager('default');
  $em2 = $this->get('doctrine')->getManager('customer');

或存储库

$customers = $this->get('doctrine')
    ->getRepository('AcmeCustomerBundle:Customer', 'customer')
    ->findAll()
;

...或动态添加连接 >

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

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

I'd like to modify a table's schema/DB name at runtime as is possible with the table name, but the ClassMetadataInfo class does not appear to expose an interface to get/set this property.

I can make do with modifying table names at runtime if absolutely necessary, but it is not an ideal solution due to the amount of tables we would then have to store in a single schema/DB.

Is there a way to achieve what I'd like to do? Thanks in advance.

Note: I need to be able to provide a fully qualified table name using a schema placeholder in my annotation-based entity mapping (like __schema_placeholder__.table_name, for cross-database joins). At runtime I would then like to dynamically remap the entity from __schema_placeholder__.table_name => real_schema_name.table_name.

解决方案

You can dynamically adjust the table names ( and mappings ) by hooking into the doctrine event-system with listeners/subscribers.

i.e. "loadClassMetadata" is one of doctrine's events you can create a listener/subscriber for as described in the cookbook article How to Register Event Listeners and Subscribers.

Example

config.yml

services:
    mapping.listener:
        class: Acme\YourBundle\EventListener\MappingListener
        tags:
            - { name: doctrine.event_listener, event: loadClassMetadata }

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);

ClassMetadata extends ClassMetadataInfo and provides a public variable "table" ( containing the mapping information provided by your annotations or yml ) which you can modify !

The public table variable is an array with the following entries:

  • name =>
  • schema =>
  • indexes => array
  • uniqueConstraints => array

You can dynamically register event-listeners/subscribers in your controller prior to saving/updating.

$mappingListener = new MappingListener();

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

$evm = $this->get('doctrine')->getManager()->->getEventManager();
$evm->addEventListener('loadClassMetadata', $mappingListener);


Furthermore you can introduce multiple database connections/names and access them in your application.

app/config/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

Then get different entity managers using ...

  $em = $this->get('doctrine')->getManager('default');
  $em2 = $this->get('doctrine')->getManager('customer');

or repositories

$customers = $this->get('doctrine')
    ->getRepository('AcmeCustomerBundle:Customer', 'customer')
    ->findAll()
;

... or add connections dynamically

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

Read more about the topic in the cookbook chapter How to work with Multiple Entity Managers and Connections.

这篇关于在Doctrine2中以编程方式修改表的架构名称?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆