11

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

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

我可以对实体进行注释,这样就不会创建表,同时仍然可以访问所有与实体相关的功能(关联,...)?

4

5 回答 5

15

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

看起来 Symfony2 不使用原始 Doctrine 命令:\Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand

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

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

src/Acme/CoreBundle/Command/DoctrineUpdateCommand.php:

<?php

namespace Acme\CoreBundle\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 Doctrine\ORM\Tools\SchemaTool;

class DoctrineUpdateCommand extends \Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand {

  protected $ignoredEntities = array(
      'Acme\CoreBundle\Entity\EntityToIgnore'
  );

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

    /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
    $newMetadatas = array();
    foreach ($metadatas as $metadata) {
      if (!in_array($metadata->getName(), $this->ignoredEntities)) {
        array_push($newMetadatas, $metadata);
      }
    }

    parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas);
  }

}
于 2014-09-20T12:46:01.303 回答
8

最终它变得相当简单,我只需将其子类\Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand化为我自己的 CLI 命令。在该子类中过滤$metadatas要传递给的数组,executeSchemaCommand()然后将其传递给父函数。

只需将此新的子类命令附加到您在教义 cli 脚本中使用的 ConsoleApplication 即可!

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

<?php
use Symfony\Component\Console\Input\InputArgument,
    Symfony\Component\Console\Input\InputOption,
    Symfony\Component\Console\Input\InputInterface,
    Symfony\Component\Console\Output\OutputInterface,
    Doctrine\ORM\Tools\SchemaTool;

class My_Doctrine_Tools_UpdateCommand extends \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand
{
    protected $name = 'orm:schema-tool:myupdate';

    protected $ignoredEntities = array(
        'Entity\Asset\Name'
    );

    protected function executeSchemaCommand(InputInterface $input, OutputInterface $output, SchemaTool $schemaTool, array $metadatas)
    {
        /** @var $metadata \Doctrine\ORM\Mapping\ClassMetadata */
        $newMetadatas = array();
        foreach($metadatas as $metadata) {
            if(!in_array($metadata->getName(), $this->ignoredEntities)){
                array_push($newMetadatas, $metadata);
            }
        }

        return parent::executeSchemaCommand($input, $output, $schemaTool, $newMetadatas);
    }
}

PS:感谢 Marco Pivetta 让我走上了正轨。https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/rwWXZ7faPsA

于 2012-09-27T09:41:51.147 回答
6

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

namespace AppBundle\EventListener;

use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;

/**
 * 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);
            }

        }
    }

}

同时注册监听器:

ignore_tables_listener:
    class: AppBundle\EventListener\IgnoreTablesListener
    tags:
        - {name: doctrine.event_listener, event: postGenerateSchema }

不需要额外的钩子。

于 2016-08-05T15:52:19.010 回答
0

$schema->getTableNames()没有工作(我不知道为什么)。

所以:

namespace AppBundle\EventListener;

use Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand;
use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;

class IgnoreTablesListener extends UpdateSchemaDoctrineCommand
{

    private $ignoredEntities = [
        'YourBundle\Entity\EntityYouWantToIgnore',
    ];

    /**
     * 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)) {
                // remove table from schema
                $schema->dropTable($table->getName());
            }
        }
    }
}

并注册服务

#services.yml
ignore_tables_listener:
    class: AppBundle\EventListener\IgnoreTablesListener
    tags:
        - {name: doctrine.event_listener, event: postGenerateSchema }

工作得很好!;)

于 2018-01-18T18:53:50.590 回答
-1

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

  1. 从 @ORM\Entity 注释中删除 @
  2. 执行学说:模式:更新
  3. 将 @ 添加到 ORM\Entity 注释

;-)

于 2018-06-08T12:25:04.620 回答