0

我需要跨数据库关系,我已经读过这个但由于映射问题而无法得到我想要的。这是我的情况

namespace App\Entity\Utility;

use Doctrine\ORM\Mapping as ORM;
use App\Entity\Crm\User;

/**
 * Description of Test
 *
 * @ORM\Table(name="fgel_utility.fgel_test")
 * @ORM\Entity(repositoryClass="App\Repository\Utility\TestRepository")
 */
class Test
{
     /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;


    /**
     * 
     * @var User
     * 
     * @ORM\ManyToOne(targetEntity="App\Entity\Crm\User")
     * @ORM\JoinColumn(name="user_cod", referencedColumnName="AUCUT") 
     */
    protected $user = null;

    public function getId()
    {
        return $this->id;
    }

    public function getUser(): User
    {
        return $this->user;
    }

    public function setId($id)
    {
        $this->id = $id;
        return $this;
    }

    public function setUser(User $user)
    {
        $this->user = $utente;
        return $this;
    }
}


namespace App\Entity\Crm;

use Doctrine\ORM\Mapping as ORM;
/**
 * 
 * @ORM\Table(name="crm.USER")
 * @ORM\Entity(repositoryClass="App\Repository\FintelGasDati\AnuteRepository")
 */
class User
{

    /**
     * 
     * @ORM\Id
     * @ORM\Column(name="AUCUT", type="integer", nullable=false)
     */
    protected $codiceCliente;

    # SOME CODE
}

我的学说.yaml

doctrine:
    orm:
        default_entity_manager: default
        entity_managers:
            #################################
            # Update schema only with this em
            #################################
            default:
                connection: mssql_1
                mappings:
                    Utility:
                        type:     "annotation"    
                        # The directory for entity (relative to bundle path)
                        dir:      '%kernel.project_dir%/src/Entity/Utility'   
                        prefix:   'App\Entity\Utility'
                        alias: Utility
            mssql_crm:
                connection: mssql_1
                mappings:
                    Crm:
                        type: "annotation" 
                        # The directory for entity (relative to bundle path)
                        dir: '%kernel.project_dir%/src/Entity/Crm'   
                        prefix: 'App\Entity\Crm'
                        alias: Crm

所以他们共享相同的连接(但不同的 em)。连接的用户有权读取/写入两个数据库(但只能将架构更改为 fgel_utility DB。两个 DB 都存储在 SQL Server 2008 中。当我尝试执行时

php bin/console doctrine:schema:update --dump-sql

我收到这个错误

在链配置的命名空间 App\Entity\Utility、FOS\UserBundle\Model 中找不到类“App\Entity\Crm\User”

4

2 回答 2

1

实际上,您可以欺骗 Doctrine 对 MySQL/MariaDB 进行跨数据库连接查询,只需在您的实体的 ORM\Table 注释中添加数据库名称的前缀:

// src/Entity/User.php
@ORM\Table(name="dbname.users")

这将被 Doctrine 在所有 SELECT、JOIN 语句中使用。

也就是说,使用此解决方案,将不会使用来自 DATABASE_URL 的 DB_NAME 或 env 文件的任何其他值,这可能会导致混淆(因为数据库名称应该与连接耦合,而不是实体)。

由于您无法解析 ORM 映射中的动态值,例如“@ORM\Table(name=%env(DBNAME)%.users”),但这里有一个示例,说明如何使用 Doctrine 中的LoadClassMetadata事件来做到这一点动态工作。

类构造函数将实体命名空间作为第一个参数,将数据库名称作为第二个参数。

当 Doctrine 运行元数据加载时,它将触发带有每个实体的元数据类的回调方法,您可以根据这些值动态处理和设置表名。

// src/DatabasePrefixer.php
class DatabasePrefixer implements EventSubscriber
{
    private $namespace;
    private $tablePrefix;

    /**
    * @param $namespace string The fully qualified entity namespace to add the prefix
    * @param $tablePrefix string The prefix
    */
    public function __construct($namespace, $tablePrefix)
    {
        $this->namespace = $namespace;
        $this->tablePrefix = $tablePrefix;
    }

    public function getSubscribedEvents()
    {
        return ['loadClassMetadata'];
    }

    public function loadClassMetadata(LoadClassMetadataEventArgs $eventArgs)
    {
        $classMetadata = $eventArgs->getClassMetadata();

        if ($this->namespace == $classMetadata->namespace) {
          $classMetadata->setTableName(sprintf('%s.%s', $this->tablePrefix, $classMetadata->table['name']));
        }
    }
}

假设你有一个 DB_NAME 环境变量,在你的 config/services.yml 中将类配置为服务,使用 Symfony 的 yaml 解析功能,以及事件标记来监听正确的 Doctrine 事件:

    // config/services.yaml
    services:
    [...]
    dbname.prefixer:
    class: App\DatabasePrefixer
    arguments:
        $namespace:   'App\Entity'
        $tablePrefix: '%env(DB_NAME)%'
        tags:
            - { name: doctrine.event_listener, event: loadClassMetadata, lazy: true }
于 2019-06-17T08:01:50.250 回答
0

根据此https://github.com/doctrine/doctrine2/issues/6350,不支持不同实体管理器(相同连接)之间的跨数据库连接。

于 2018-05-03T14:38:06.357 回答