Hi想要在两个实体之间建立连接。实体位于不同的数据库中:
以下是我如何设置数据库配置:
doctrine:
dbal:
default_connection: default
connections:
default:
driver: %database_driver%
host: %database_host%
port: %database_port%
dbname: %database_name%
user: %database_user%
password: %database_password%
charset: UTF8
mapping_types:
enum: string
data_warehouse:
driver: %database_data_warehouse_driver%
host: %database_data_warehouse_host%
port: %database_data_warehouse_port%
dbname: %database_data_warehouse_name%
user: %database_data_warehouse_user%
password: %database_data_warehouse_password%
charset: UTF8
mapping_types:
enum: string
orm:
auto_generate_proxy_classes: %kernel.debug%
default_entity_manager: default
entity_managers:
default:
connection: default
mappings:
MyBundle1: ~
data_warehouse:
connection: data_warehouse
mappings:
MyBundle2: ~
这些是我的实体:
namespace MyBundle1Entity;
use MyBundle1EntityMyBundle2Entity;
class MyBundle1Entity
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer", nullable=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
}
namespace MyBundle2Entity;
class MyBundle2Entity
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer", nullable=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var MyBundle1Entity
*
* @ORMManyToOne( targetEntity="MyBundle1EntityMyBundle1Entity")
* @ORMJoinColumn(name="my_bundle1_entity_id", nullable=true)
*/
private $myBundle1Entity;
}
当我尝试使用条令:模式:更新命令时,我得到了一个错误:
php app/console doctrine:schema:create --dump-sql --em=data_warehouse
错误:
[原则\Common\Persistence\MMapping\MappingException]
在链配置的命名空间My\Bundle2\Entity\Bundle2Entity 中找不到类"My\Bundle 1\Entity\Bundle 1Entity">
我的设置是正确的还是我做了完全错误的事情?我假设我定义了两个实体管理器和它们之间的连接,并告诉它们必须处理哪些捆绑包。我确保每个捆绑包中只有来自一个数据库的实体。
感谢您的帮助
这个问题看起来很老,但从未得到回答。我希望这个答案能帮助谷歌的同事们理解这个问题。
不能跨实体经理在实体之间建立直接关系。不过,如果捆绑包共享同一个实体管理器,则可以跨捆绑包建立关系。
使用同一实体管理器[2.2+]的两个实体之间的关系:
查看Symfony关于问题的文档
本质上,在Bundle1中,创建一个接口,然后在实体上实现它。在Bundle2中,将@ManyToOne注释链接到接口,而不是实体本身。然后,在配置中告诉Symfony如何解析接口。
Bundle1:
<?php
// src/My/Bundle1/Entity/Bundle1Entity.php
namespace MyBundle1Entity;
use MyBundle1EntityMyBundle2Entity; // <-- NOT NEEDED
interface Bundle1EntityInterface {}
class MyBundle1Entity implements Bundle1EntityInterface
{
// ...
}
Bundle2:
<?php
// src/My/Bundle2/Entity/Bundle2Entity.php
namespace MyBundle2Entity;
class MyBundle2Entity
{
// ...
/**
* @var MyBundle1Entity
*
* @ORMManyToOne(targetEntity="MyBundle1EntityBundle1EntityInterface")
* @ORMJoinColumn(name="my_bundle1_entity_id", nullable=true)
*/
private $myBundle1Entity;
}
应用程序配置:
# app/config/config.yml
doctrine:
# ....
orm:
# ....
resolve_target_entities:
MyBundle1EntityBundle1EntityInterface: MyBundle1EntityBundle1Entity
使用不同实体管理器的两个实体之间的关系
因为实体不能直接绑定,所以必须挂接postLoad事件来设置引用,同时手动持久化id。有关混合MongoDB对象和ORM对象的示例和解释,请参阅文档。
下面是一个骨架(删除了getter/setter),使用了两个实体管理器:
实体:
<?php
// src/My/Bundle1/Entity/Bundle1Entity.php
namespace MyBundle1Entity;
class MyBundle1Entity
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer", nullable=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
}
// src/My/Bundle2/Entity/Bundle2Entity.php
namespace MyBundle2Entity;
class MyBundle2Entity
{
/**
* @var integer
*
* @ORMColumn(name="id", type="integer", nullable=false)
* @ORMId
* @ORMGeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var integer
*
* @ORMColumn(type="integer")
*/
private $myBundle1EntityId;
/**
* @var MyBundle1Entity
*/
private $myBundle1Entity;
public function setMyBundle1Entity($entity)
{
$this->myBundle1EntityId = $entity->getId();
$this->myBundle1Entity = $entity;
}
}
事件侦听器:
<?php
use DoctrineORMEntityManager;
use DoctrineORMEventLifecycleEventArgs;
class MyEventSubscriber
{
public function __construct(EntityManager $bundle1Em)
{
$this->bundle1Em = $bundle1Em;
}
public function postLoad(LifecycleEventArgs $eventArgs)
{
$myBundle2Entity = $eventArgs->getEntity();
$defaultEm = $eventArgs->getEntityManager();
$myBundle2EntityReflProp = $defaultEm->getClassMetadata('EntityMyBundle2Entity')
->reflClass->getProperty('myBundle1Entity');
$myBundle2EntityReflProp->setAccessible(true);
$myBundle2EntityReflProp->setValue(
$myBundle1Entity, $this->bundle1Em->getReference('EntityMyBundle1Entity', $myBundle2Entity->getMyBundle1Id())
);
}
}
显然,您必须注册事件侦听器,并将bundle 1的实体管理器作为参数传递。