mysql – Doctrine:两个数据库中两个实体之间的关系

我正在使用
MySQL和Doctrine 2(使用Symfony 3).

我想在两个独立的数据库中的两个实体之间建立一个ManyToMany关系.

我认为Doctrine不处理这个问题,至少不是以原生的方式处理.无论如何要执行它,我在表定义上使用schema属性.

假设我有这两个实体:

/**
 * @ORM\Table(schema="bdd2", name="site")
 */
class Site {}

/**
 * @ORM\Table(name="user")
 */
class User {}

我没有在User实体上使用schema属性,因为我的实体管理器被配置为使用它的数据库,所以它没用.我以这种方式在User 1中建立关系:

/**
 * @ORM\ManyToMany(targetEntity="[...]")
 */
private $sites;

非常简单.在代码方面,它起作用,关系是有效的.

在数据库方面,它不行,因为doctrine生成的user_site表只有一个外键(对于用户):它不包含第二个数据库的外键.该字段存在,有索引,但不是外键.

如果我自己添加外键,每次我做一个php bin / console doctrine:schema:update –dump-sql Doctrine想要删除它.

问题是 :
如何让学说创建第二个外键?
或者如果不可能,我怎样才能使学说无视我自己创造的那个?

最佳答案 这是我建议的解决方案,昨天在我的评论中我无法正确解释.

当你运行doctrine-schema-update(或doctrine-migrations-diff,见https://symfony.com/doc/current/bundles/DoctrineMigrationsBundle/index.html)时,doctrine会做3件事:

>它从映射信息(例如实体注释)生成模式,然后触发postGenerateSchema事件
>它从当前数据库生成模式(通过反向工程)
>它比较两个生成的模式,并生成第二个模式与第一个模式相同的SQL代码.

因此,如果您操纵第一个模式,您可以避免Doctrine做您不喜欢的事情.

在这个例子中,我有一些实体在db中实际上是VIEWS,而不是TABLES.所以我告诉学说不要生成他们的表和相关表上的所有FKs约束.您可以轻松地从这个工作脚本开始,并适应您的需求.

最好的祝福.
这是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);
            }

        }

    }

}

这是服务配置(app / config / services.yml)

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