运行架构管理器更新时忽略 Doctrine2 实体



>我定义了一个映射到数据库中视图的教义实体。一切正常,实体关系按预期工作正常。

现在的问题是,在 CLI 上运行orm:schema-manager:update时,会为此实体创建一个表,这是我想防止的。此实体已有一个视图,无需为其创建表。

我是否可以对实体进行批注,以便在仍保留对所有实体相关功能(关联等)的访问权限的同时不创建表?

基于Marco Pivetta帖子中受启发的ChrisR的原始算法,如果您使用的是Symfony2,我将在此处添加解决方案:

看起来Symfony2没有在以下位置使用原始的Doctrine命令:\Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand

相反,它使用捆绑包中的那个:\Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand

所以基本上这是必须扩展的类,最终拥有:

src/Acme/CoreBundle/Command/DoctrineUpdateCommand.php

<?php
namespace AppCommand;
use DoctrineBundleDoctrineBundleCommandProxyUpdateSchemaDoctrineCommand;
use DoctrineORMMappingClassMetadata;
use DoctrineORMToolsSchemaTool;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentConsoleStyleSymfonyStyle;
class DoctrineUpdateCommand extends UpdateSchemaDoctrineCommand
{
    protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui): ?int
    {
        $ignoredEntities = [
            'AppEntityEntityToIgnore',
        ];
        $metadatas = array_filter($metadatas, static function (ClassMetadata $classMetadata) use ($ignoredEntities) {
            return !in_array($classMetadata->getName(), $ignoredEntities, true);
        });
        return parent::executeSchemaCommand($input, $output, $schemaTool, $metadatas, $ui);
    }
}

最终它相当简单,我只需要将DoctrineORMToolsConsoleCommandSchemaToolUpdateCommand子类化到我自己的 CLI 命令中。在该子类中,筛选传递给executeSchemaCommand()$metadatas数组,然后将其传递给父函数。

只需将这个新的子类化命令附加到您在 doctrine cli 脚本中使用的控制台应用程序即可完成!

下面是扩展命令,在生产中,您可能希望从配置或其他东西中获取$ignoredEntities属性,这应该会让您上路。

<?php
use DoctrineORMToolsConsoleCommandSchemaToolUpdateCommand;
use DoctrineORMToolsSchemaTool;
use SymfonyComponentConsoleInputInputInterface;
use SymfonyComponentConsoleOutputOutputInterface;
use SymfonyComponentConsoleStyleSymfonyStyle;
class My_Doctrine_Tools_UpdateCommand extends UpdateCommand
{
    protected $name = 'orm:schema-tool:myupdate';
    protected $ignoredEntities = array(
        'EntityAssetName'
    );
    protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui)
    {
        /** @var $metadata DoctrineORMMappingClassMetadata */
        $newMetadata = [];
        foreach ($metadatas as $metadata) {
            if (!in_array($metadata->getName(), $this->ignoredEntities)) {
                $newMetadata[] = $metadata;
            }
        }
        return parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadata, $ui);
    }
}

PS:感谢马可·皮维塔让我走上了正确的轨道。 https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/rwWXZ7faPsA

相当古老的,但使用Doctrine2也没有任何价值的解决方案:postGenerateSchema事件侦听器 - 对我来说,这比覆盖要好 Doctrine类:

namespace AppDoctrineListener;
use DoctrineORMToolsEventGenerateSchemaEventArgs;
/**
 * IgnoreTablesListener class
 */
class IgnoreTablesListener
{
    private $ignoredTables = [
        'table_name_to_ignore',
    ];
    public function postGenerateSchema(GenerateSchemaEventArgs $args)
    {
        $schema = $args->getSchema();
        $tableNames = $schema->getTableNames();
        foreach ($tableNames as $tableName) {
            if (in_array($tableName, $this->ignoredTables)) {
                // remove table from schema
                $schema->dropTable($tableName);
            }
        }
    }
}

同时注册侦听器:

# config/services.yaml
services:
    ignore_tables_listener:
        class: AppDoctrineListenerIgnoreTablesListener
        tags:
            - {name: doctrine.event_listener, event: postGenerateSchema }

不需要额外的钩子。

在 Doctrine 2.7.0 中引入了新的 SchemaIgnoreClasses 实体管理器配置选项,该选项基本上忽略了任何架构操作中配置的类。

要将其与Symfony一起使用,我们只需要在Doctrine实体管理器配置中添加schema_ignore_classes键,如下所示:

doctrine:
    dbal:
        # your dbal configuration
    orm:
        default_entity_manager: default
        entity_managers:
            default:
                connection: default
                mappings:
                    Main:
                        is_bundle: false
                        type: annotation
                        dir: '%kernel.project_dir%/src/Entity/Main'
                        prefix: 'AppEntityMain'
                        alias: Main
                schema_ignore_classes:
                    - ReferenceToMyClass
                    - ReferenceToMyOtherClass

$schema->getTableNames()不起作用(我不知道为什么)。

所以:

<?php
namespace AppBundleEventListener;
use DoctrineBundleDoctrineBundleCommandProxyUpdateSchemaDoctrineCommand;
use DoctrineORMToolsEventGenerateSchemaEventArgs;
class IgnoreTablesListener extends UpdateSchemaDoctrineCommand
{
    private $ignoredEntities = [
        'YourBundleEntityEntityYouWantToIgnore',
    ];
    /**
     * Remove ignored tables /entities from Schema
     *
     * @param GenerateSchemaEventArgs $args
     */
    public function postGenerateSchema(GenerateSchemaEventArgs $args)
    {
        $schema = $args->getSchema();
        $em = $args->getEntityManager();

        $ignoredTables = [];
        foreach ($this->ignoredEntities as $entityName) {
            $ignoredTables[] = $em->getClassMetadata($entityName)->getTableName();
        }

        foreach ($schema->getTables() as $table) {
            if (in_array($table->getName(), $ignoredTables, true)) {
                // remove table from schema
                $schema->dropTable($table->getName());
            }
        }
    }
}

并注册一项服务

# config/services.yaml
services:
    ignore_tables_listener:
        class: AppBundleEventListenerIgnoreTablesListener
        tags:
            - {name: doctrine.event_listener, event: postGenerateSchema }

工作正常! ;)

如果问题只是在db_view中产生错误,那么在调用doctrine:schema:update命令时,为什么不是最简单的方法:

  1. 从@ORM\实体注释中删除 @
  2. 执行策略:架构:更新
  3. 将 @ 添加到 ORM\实体注释

;-)

相关内容

  • 没有找到相关文章

最新更新