Ignore a Doctrine2 Entity when running schema-manager update

后端 未结 5 1755
天涯浪人
天涯浪人 2020-12-06 17:51

I\'ve got a Doctrine Entity defined that maps to a View in my database. All works fine, the Entity relations work fine as expected.

Problem now is that when running

相关标签:
5条回答
  • 2020-12-06 18:01

    Based on the original alswer of ChrisR inspired in Marco Pivetta's post I'm adding here the solution if you're using Symfony2:

    Looks like Symfony2 doesn't use the original Doctrine command at: \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand

    Instead it uses the one in the bundle: \Doctrine\Bundle\DoctrineBundle\Command\Proxy\UpdateSchemaDoctrineCommand

    So basically that is the class that must be extended, ending up in having:

    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);
      }
    
    }
    
    0 讨论(0)
  • 2020-12-06 18:03

    Eventually it was fairly simple, I just had to subclass the \Doctrine\ORM\Tools\Console\Command\SchemaTool\UpdateCommand into my own CLI Command. In that subclass filter the $metadatas array that's being passed to executeSchemaCommand() and then pass it on to the parent function.

    Just attach this new subclassed command to the ConsoleApplication you are using in your doctrine cli script and done!

    Below is the extended command, in production you'll probably want to fetch the $ignoredEntities property from you config or something, this should put you on the way.

    <?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: credits go to Marco Pivetta for putting me on the right track. https://groups.google.com/forum/?fromgroups=#!topic/doctrine-user/rwWXZ7faPsA

    0 讨论(0)
  • 2020-12-06 18:06

    $schema->getTableNames() was not working (I don't know why).

    So:

    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());
                }
            }
        }
    }
    

    And Register a service

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

    Worked fine! ;)

    0 讨论(0)
  • 2020-12-06 18:11

    Quite old one but there is also worth nothing solution using Doctrine2: postGenerateSchema event listener - for me it's better than overriding Doctrine classes:

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

    Also register listener:

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

    No extra hooks is necessary.

    0 讨论(0)
  • 2020-12-06 18:17

    If problem is only with producing errors in db_view, when calling doctrine:schema:update command, why not simplest way:

    1. remove @ from @ORM\Entity annotation
    2. execute doctrine:schema:update
    3. add @ to ORM\Entity annotation

    ;-)

    0 讨论(0)
提交回复
热议问题