如何在 symfony2 中设置表前缀指示替代答案

2022-08-30 20:20:02

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

最好是默认为所有实体设置它,但可以选择覆盖单个实体。


答案 1

我自己刚刚弄清楚了这一点,我想就如何实现这一目标有所了解。

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

指示

  1. 打开捆绑包的资源/配置/服务.yml

  2. 定义表前缀参数:
    请务必更改 mybundlemyprefix_

    parameters:
        mybundle.db.table_prefix: myprefix_
    
  3. 添加新服务:

    services:
        mybundle.tblprefix_subscriber:
            class: MyBundle\Subscriber\TablePrefixSubscriber
            arguments: [%mybundle.db.table_prefix%]
            tags:
                - { name: doctrine.event_subscriber }
    
  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;
                }
            }
        }       
    }
    
  5. postgres 用户的可选步骤:对序列执行类似操作

  6. 享受

答案 2

替代答案

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

原则2 命名策略

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

只需查找“短类名”(不带其命名空间)即可推断表名。DefaultNamingStrategy

做同样的事情,但它也小写和“欠修饰”“短类名称”。UnderscoreNamingStrategy

您的类可以扩展上述任一(只要您认为合适),并重写 and 方法,以允许您指定应如何构造表名(使用前缀)。CustomNamingStrategyclassToTableNamejoinTableName

例如,我的类根据命名空间约定扩展并查找捆绑包名称,并将其用作所有表的前缀。CustomNamingStrategyUnderscoreNamingStrategy


Symfony2 命名策略

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

doctrine:
    # ...

    orm:
        # ...
        #naming_strategy: doctrine.orm.naming_strategy.underscore
        naming_strategy: my_bundle.naming_strategy.prefixed_naming_strategy

优点和缺点

优点:

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

缺点:

  • 对映射元数据的零访问权限 - 您只有作为参数提供给您的上下文(这也可能是一件好事,因为它强制约定而不是异常);
  • 需要教义2.3(现在不是那么多骗子,可能是在2011年提出这个问题的时候:-));

推荐