Doctrine: Relations between two entities in two databases

Here is the solution I suggest, yesterday in my comment I couldn't explain it properly.

When you run doctrine-schema-update (or doctrine-migrations-diff, see https://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html), doctrine does 3 things:

  • it generates the schema from mapping informations (e.g. entity annotations), then the postGenerateSchema event is triggered
  • it generates the schema from the current db (through reverse engeneering)
  • it compares the two generated schemas and generate the SQL code that needs for the second schema to be the same as the first.

So if you manipulate the first schema, you can avoid Doctrine from doing what you don't like.

In this example, I have some entities that are actually VIEWS in the db, not TABLES. So I tell doctrine to don't generate their tables and all the FKs contraints on related table. You can easily start from this working script and adapt to your needs.

Best regards. this is AppBundle/Utils/IgnoreTablesListener.php

<?php


namespace AppBundle\Utils;

use Doctrine\ORM\Tools\Event\GenerateSchemaEventArgs;


class IgnoreTablesListener {
    private $ignoredEntities = null;
    private $ignoredTables = null;


    public function __construct($ignoredEntities) {
        $this->ignoredEntities=$ignoredEntities;
        $this->ignoredTables=array();
    }

    /**
     * Remove ignored entities from Schema
     * This listener is called when the schema as been generated, from entities data mapping (i.e. in doctrine-schema-update or in doctrine:migrations:diff)
     * 
     * @param GenerateSchemaEventArgs $args
     */
    public function postGenerateSchema(GenerateSchemaEventArgs $args)
    {

        $schema = $args->getSchema();
        $em = $args->getEntityManager();

        $ignoredTables = $this->ignoredTables;

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

        foreach ($schema->getTableNames() as $longTableName) {
            $table=$schema->getTable($longTableName);
            $table_name=strtolower($table->getShortestName($table->getNamespaceName()));

            $fks=$table->getForeignKeys();
            foreach ($fks as $fk) { 
                $foreign_table_name=strtolower($fk->getForeignTableName());

                if (in_array($foreign_table_name, $ignoredTables)) {    //if the fk points to one of the entities i'm ignoring
                    $table->removeForeignKey($fk->getName());   //i remove fk constrains from generated schema (NOT FROM MY CURRENT DB!!!)
//                  dump('removed FK '.$fk->getName().' from '.$table_name.' pointing to '.$foreign_table_name.'.['.implode(', ', $fk->getForeignColumns()).']');
                } 
            }
            if (in_array($table_name, $ignoredTables)) { //if i have to ignore the $table_name table
                $schema->dropTable($longTableName);     //remove the table from generated schema -- NOT FROM DB!!
//              dump('removed ignored table/entity '.$longTableName);
            }

        }

    }

}

and this is the service configuration (app/config/services.yml)

..
app.ignoretableslistener:
    class: AppBundle\Utils\IgnoreTablesListener
    arguments: ['AppBundle:MyEntityToBeIgnoredBecauseItIsAView1', 'AppBundle:MyEntityToBeIgnoredBecauseItIsAView2']
    tags:
        - {name: doctrine.event_listener, event: postGenerateSchema }
..