如何在symfony2中设置表前缀

can*_*nni 19 php symfony doctrine-orm

就像问题主题一样,我如何在symfony2中设置默认表格前缀?

对于所有实体,默认情况下可以设置为最佳,但可以选择覆盖单个实体.

sim*_*aun 46

刚刚想到这一点,我想详细说明如何实现这一目标.

Symfony 2&Doctrine 2.1
注意:我使用YML进行配置,这就是我要展示的内容.

说明

  1. 打开你的bundle的Resources/config/services.yml

  2. 定义表前缀参数:
    确保更改 mybundlemyprefix_

    parameters:
        mybundle.db.table_prefix: myprefix_
    
    Run Code Online (Sandbox Code Playgroud)
  3. 添加新服务:

    services:
        mybundle.tblprefix_subscriber:
            class: MyBundle\Subscriber\TablePrefixSubscriber
            arguments: [%mybundle.db.table_prefix%]
            tags:
                - { name: doctrine.event_subscriber }
    
    Run Code Online (Sandbox Code Playgroud)
  4. 创建MyBundle\Subscriber\TablePrefixSubscriber.php

    <?php
    namespace MyBundle\Subscriber;
    
    use Doctrine\ORM\Event\LoadClassMetadataEventArgs;
    
    class TablePrefixSubscriber implements \Doctrine\Common\EventSubscriber
    {
        protected $prefix = '';
    
        public function __construct($prefix)
        {
            $this->prefix = (string) $prefix;
        }
    
        public function getSubscribedEvents()
        {
            return array('loadClassMetadata');
        }
    
        public function loadClassMetadata(LoadClassMetadataEventArgs $args)
        {
            $classMetadata = $args->getClassMetadata();
            if ($classMetadata->isInheritanceTypeSingleTable() && !$classMetadata->isRootEntity()) {
                // if we are in an inheritance hierarchy, only apply this once
                return;
            }
    
            $classMetadata->setTableName($this->prefix . $classMetadata->getTableName());
    
            foreach ($classMetadata->getAssociationMappings() as $fieldName => $mapping) {
                if ($mapping['type'] == \Doctrine\ORM\Mapping\ClassMetadataInfo::MANY_TO_MANY 
                        && array_key_exists('name', $classMetadata->associationMappings[$fieldName]['joinTable']) ) {     // Check if "joinTable" exists, it can be null if this field is the reverse side of a ManyToMany relationship
                    $mappedTableName = $classMetadata->associationMappings[$fieldName]['joinTable']['name'];
                    $classMetadata->associationMappings[$fieldName]['joinTable']['name'] = $this->prefix . $mappedTableName;
                }
            }
        }       
    }
    
    Run Code Online (Sandbox Code Playgroud)
  5. postgres用户的可选步骤:为序列做类似的事情

  6. 请享用


Mih*_*ncu 11

替代答案

这是一个考虑到Doctrine2中可用的新功能的更新.

Doctrine2命名策略

Doctrine2使用NamingStrategy实现从类名到表名或从属性名到列名的转换的类.

DefaultNamingStrategy只是为了推导出表名称查找"短类名"(不带其命名空间).

UnderscoreNamingStrategy做同样的事情,但它也小写字母和"underscorifies""短类名".

您的CustomNamingStrategy类可以扩展上述任何一个(如您所见)并覆盖classToTableNamejoinTableName方法,以允许您指定应如何构造表名(使用前缀).

例如,我的CustomNamingStrategy类扩展了UnderscoreNamingStrategy并根据命名空间约定找到了包名称,并将其用作所有表的前缀.


Symfony2命名策略

在Symfony2中使用上述内容需要将您的CustomNamingStragery类声明为服务,然后在您的配置中引用它:

doctrine:
    # ...

    orm:
        # ...
        #naming_strategy: doctrine.orm.naming_strategy.underscore
        naming_strategy: my_bundle.naming_strategy.prefixed_naming_strategy
Run Code Online (Sandbox Code Playgroud)

利弊

优点:

  • 运行一段代码来执行一项任务 - 直接调用命名策略类并使用其输出;
  • 结构的清晰度 - 你没有使用事件来运行代码,这些代码改变了已经由其他代码构建的东西;
  • 更好地访问命名约定的所有方面;

缺点:

  • 零访问映射元数据 - 你只有作为参数给你的上下文(这也是一件好事,因为它强制约定而不是异常);
  • 需要学说2.3(现在不是那么多了,可能是在2011年问这个问题的时候:-));