Symfony 4.4 升级 - DoctrineUpdateCommand 不再从控制台命令调用

Symfony 4.4 Upgrade - DoctrineUpdateCommand no longer called from console command

我正在将我们的 Symfony 应用程序从 3.4 版升级到 4.4 版,其中包括将 Doctrine 从 1.12 升级到 2.3。我之前写过 class 将结果修改为 doctrine:schema:update command,效果很好,但现在似乎不起作用。 class 如下。

为了修改 doctrine:schema:update,我创建了一个名为 DoctrineUpdateCommand 的 class,它扩展了 \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand,并将其放在包的 Command 文件夹中。这就是所需要的。我参考了这个答案来弄清楚如何去做:How to set up entity (doctrine) for database view in Symfony 2.

我们需要覆盖 doctrine:schema:update 命令,因为我们的一个实体引用 MySQL 视图而不是 MySQL table。此外,实体被引用为独立实体和多对多连接。覆盖 class 导致实体和连接被忽略。它还添加了一个 sql 语句来创建视图。

升级后,如果我 运行 php console doctrine:schema:update --dump-sql,我得到这些结果:

19:08:16 CRITICAL  [console] Error thrown while running command "doctrine:schema:update --dump-sql". Message: "The table with name 'nest_qa.assignedrole_privilegerole' already exists." ["exception" => Doctrine\DBAL\Schema\SchemaException^ { …},"command" => "doctrine:schema:update --dump-sql","message" => "The table with name 'nest_qa.assignedrole_privilegerole' already exists."]

In SchemaException.php line 112:

  The table with name 'nest_qa.assignedrole_privilegerole' already exists.

我相当确定不再调用 doctrine 命令的扩展,而是使用默认命令,但我不知道如何更改它。任何帮助将不胜感激。

原文如下class:

<?php 

namespace ApiBundle\Command;

use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use Symfony\Component\Console\Style\SymfonyStyle;
use Doctrine\ORM\Tools\SchemaTool;

class DoctrineUpdateCommand extends \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand{

    protected $ignoredEntities = array(
        'ApiBundle\Entity\AssignedrolePrivilegerole',
    );
    protected $ignoreAssociationMappings = array(
        'ApiBundle\Entity\Privilegerole' => 'assignedroles',
        'ApiBundle\Entity\Assignedrole' => 'privilegeroles',
    );

    protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas, SymfonyStyle $ui) {

        /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
        $newMetadatas = array();
        foreach ($metadatas as $metadata) {
            if (array_key_exists($metadata->getName(), $this->ignoreAssociationMappings)) {
                if(array_key_exists($this->ignoreAssociationMappings[$metadata->getName()], $metadata->getAssociationMappings())){
                    unset($metadata->associationMappings[$this->ignoreAssociationMappings[$metadata->getName()]]);
                }
            }
            //If metadata element is not in the ignore array, add it to the new metadata array 
            if (!in_array($metadata->getName(), $this->ignoredEntities)){
                array_push($newMetadatas, $metadata);
            }
        }
        
        parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas, $ui);
        $output->writeln("------Create view for assignedrole_privilegerole");
        $output->writeln("CREATE VIEW `assignedrole_privilegerole`  AS  select `Assignedrole`.`id` AS `assignedrole_id`,`Privilegerole`.`id` AS `privilegerole_id` from (`Assignedrole` join `Privilegerole`) where ((`Assignedrole`.`role_id` = `Privilegerole`.`role_id`) and ((`Assignedrole`.`unit_id` = `Privilegerole`.`unit_id`) or `Privilegerole`.`unit_id` in (select `Unittree`.`ancestor_id` from `Unittree` where (`Unittree`.`descendant_id` = `Assignedrole`.`unit_id`)))) ;");
    }

}

symfony <4.x 中的控制台命令是通过扫描捆绑包中的 Command 文件夹注册的。由于捆绑在 symfony 4+ 中已过时,您必须通过标记命令 class 或使用 DI 自动配置来在服务定义中定义命令。

选项 1: 显式添加 console.command tag 到服务定义:

services:
    ApiBundle\Command\DoctrineUpdateCommand:
        tags:
            - { name: twig.extension }

选项 2: 使用 DI autoconfiguration:

services:
    ApiBundle\Command\DoctrineUpdateCommand:
        autoconfigure: true

将您的 class 注册为控制台命令后,它必须覆盖默认命令。

有关更多信息,请参阅 symfony 文档:Console Command