问题描述
你好想在两个实体之间建立联系。实体位于不同的数据库中:这是我如何设置我的数据库配置:
doctrine:
dbal:
default_connection:默认
连接:
默认值:
驱动程序:%database_driver%
主机:%database_host %
port:%database_port%
dbname:%database_name%
用户:%database_user%
密码:%database_password%
charset:UTF8
mapping_types:
枚举:string
data_warehouse:
驱动程序:%database_data_warehouse_driver%
主机:%database_data_warehouse_host%
端口:%database_data_warehouse_port%
dbname:%database_data_warehouse_name%
用户:%database_data_warehouse_user%
密码:%database_data_warehouse_password%
chars et:UTF8
mapping_types:
枚举:string
orm:
auto_generate_proxy_classes:%kernel.debug%
default_entity_manager:默认
entity_managers:
默认值:
连接:默认
映射:
MyBundle1:〜
data_warehouse:
连接:data_warehouse
映射:
MyBundle2:〜
这些是我的实体:
命名空间My\Bundle1\Entity;
使用My\Bundle1\Entity\MyBundle2Entity;
class MyBundle1Entity
{
/ **
* @var整数
*
* @ ORM\Column(name =id ,type =integer,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
private $ ID;
}
命名空间My\Bundle2\Entity;
class MyBundle2Entity
{
/ **
* @var整数
*
* @ ORM\Column(name =id ,type =integer,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
private $ ID;
/ **
* @var MyBundle1Entity
*
* @ ORM\ManyToOne(targetEntity =My\Bundle1\Entity\\ \\ MyBundle1Entity)
* @ ORM\JoinColumn(name =my_bundle1_entity_id,nullable = true)
* /
private $ myBundle1Entity;
}
当我尝试使用原则:schema:update命令时,我得到一个错误:
php app / console doctrine:schema:create --dump-sql --em = data_warehouse
错误:
[Doctrine\Common\Persistence\\ \\Mapping\MappingException]
在链配置的命名空间中找不到类My\Bundle1\Entity\Bundle1EntityMy\Bundle2\Entity\Bundle2Entity
我的设置是正确的还是我完全错了?我假设我定义了两个实体管理器,并且有连接并告诉他们,他们必须处理哪些bundle。我确保每个包中只有一个数据库中的实体。
感谢您的帮助
看起来这个问题很旧,但从未回答过。我希望这个答案有助于Google员工绊倒这个问题。
您不能在实体经理之间建立实体之间的直接关系。您可以在捆绑中设置关系,但是如果他们共享相同的实体管理员。
使用相同实体管理器的2个实体之间的关系[2.2+]:
看看
本质上,在Bundle1中,创建一个接口,然后在您的实体上实现。在Bundle2中,将@ManyToOne注释与实体本身链接。然后,告诉Symfony在配置中如何解决界面。
Bundle1:
<?php
// src / My / Bundle1 / Entity / Bundle1Entity.php
命名空间My\Bundle1\Entity;
使用My\Bundle1\Entity\MyBundle2Entity; //< - NOT NEEDED
interface Bundle1EntityInterface {}
class MyBundle1Entity implements Bundle1EntityInterface
{
// ...
Bundle2:
<?php
// src / My / Bundle2 / Entity / Bundle2Entity.php
命名空间My\Bundle2\Entity;
class MyBundle2Entity
{
// ...
/ **
* @var MyBundle1Entity
*
* @ ORM\ManyToOne(targetEntity =My\Bundle1\Entity\Bundle1EntityInterface)
* @ ORM\JoinColumn(name =my_bundle1_entity_id,nullable = true)
* /
private $ myBundle1Entity;
}
应用配置:
#app / config / config.yml
doctrine:
#....
orm:
#....
resolve_target_entities:
My\Bundle1\Entity\Bundle1EntityInterface:My\Bundle1\Entity\Bundle1Entity
使用不同实体管理器的2个实体之间的关系
由于实体不能直接绑定,钩入postLoad事件以设置引用,同时手动持久化id。请参阅,将一个MongoDB对象与一个ORM对象进行混合的例子和说明。
这是一个使用2个实体管理器的骨架(getters / setters removed)
实体:
<?php
// src / My / Bundle1 / Entity / Bundle1Entity.php
命名空间My\Bundle1\Entity;
class MyBundle1Entity
{
/ **
* @var整数
*
* @ ORM\Column(name =id ,type =integer,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
private $ ID;
}
// src / My / Bundle2 / Entity / Bundle2Entity.php
命名空间My\Bundle2\Entity;
class MyBundle2Entity
{
/ **
* @var integer
*
* @ ORM\Column(name =id,type = integer,nullable = false)
* @ ORM\Id
* @ ORM\GeneratedValue(strategy =IDENTITY)
* /
private $ id;
/ **
* @var整数
*
* @ ORM\Column(type =integer)
* /
private $ myBundle1EntityId;
/ **
* @var MyBundle1Entity
* /
private $ myBundle1Entity;
public function setMyBundle1Entity($ entity)
{
$ this-> myBundle1EntityId = $ entity-> getId();
$ this-> myBundle1Entity = $ entity;
}
}
事件监听器:
<?php
使用Doctrine\ORM\EntityManager;
使用Doctrine\ORM\Event\LifecycleEventArgs;
class MyEventSubscriber
{
public function __construct(EntityManager $ bundle1Em)
{
$ this-> bundle1Em = $ bundle1Em;
}
public function postLoad(LifecycleEventArgs $ eventArgs)
{
$ myBundle2Entity = $ eventArgs-> getEntity();
$ defaultEm = $ eventArgs-> getEntityManager();
$ myBundle2EntityReflProp = $ defaultEm-> getClassMetadata('Entity\MyBundle2Entity')
- > reflClass-> getProperty('myBundle1Entity');
$ myBundle2EntityReflProp-> setAccessible(true);
$ myBundle2EntityReflProp-> setValue(
$ myBundle1Entity,$ this-> bundle1Em-> getReference('Entity\MyBundle1Entity',$ myBundle2Entity-> getMyBundle1Id())
) ;
}
}
显然,你必须注册事件监听器并通过捆绑1的实体管理器作为参数。
Hi want to make a join between two entities. The entities are in different databases:
Here is how I set up my database config:
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: ~
And these are my entities:
namespace My\Bundle1\Entity;
use My\Bundle1\Entity\MyBundle2Entity;
class MyBundle1Entity
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
}
namespace My\Bundle2\Entity;
class MyBundle2Entity
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var MyBundle1Entity
*
* @ORM\ManyToOne( targetEntity="My\Bundle1\Entity\MyBundle1Entity")
* @ORM\JoinColumn(name="my_bundle1_entity_id", nullable=true)
*/
private $myBundle1Entity;
}
When I try to use the doctrine:schema:update command, I get an error:
php app/console doctrine:schema:create --dump-sql --em=data_warehouse
Error:
[Doctrine\Common\Persistence\Mapping\MappingException]
The class 'My\Bundle1\Entity\Bundle1Entity' was not found in the chain configured namespaces My\Bundle2\Entity\Bundle2Entity
Is my setup correct or am I doeing something completely wrong? I assume that I define two entity managers and there connections and tell them, what bundles they have to handle. I ensure that there are only entities from one database in each bundle.
Thanks for your help
It looks like this question is old, but was never answered. I'm hoping this answer helps fellow Googlers stumbling across this question.
You can't set up a direct relationship between entities across entity managers. You can set up relationships across bundles, though, if they share the same entity manager.
Relationships between 2 entities using the same entity manager [2.2+]:
Have a look at the Symfony docs on the issue
Essentially, in Bundle1, create an interface, then implement it on your entity. In Bundle2, link your @ManyToOne annotation to the interface instead of the entity itself. Then, tell Symfony in the config how to resolve the interface.
Bundle1:
<?php
// src/My/Bundle1/Entity/Bundle1Entity.php
namespace My\Bundle1\Entity;
use My\Bundle1\Entity\MyBundle2Entity; // <-- NOT NEEDED
interface Bundle1EntityInterface {}
class MyBundle1Entity implements Bundle1EntityInterface
{
// ...
}
Bundle2:
<?php
// src/My/Bundle2/Entity/Bundle2Entity.php
namespace My\Bundle2\Entity;
class MyBundle2Entity
{
// ...
/**
* @var MyBundle1Entity
*
* @ORM\ManyToOne(targetEntity="My\Bundle1\Entity\Bundle1EntityInterface")
* @ORM\JoinColumn(name="my_bundle1_entity_id", nullable=true)
*/
private $myBundle1Entity;
}
App Config:
# app/config/config.yml
doctrine:
# ....
orm:
# ....
resolve_target_entities:
My\Bundle1\Entity\Bundle1EntityInterface: My\Bundle1\Entity\Bundle1Entity
Relationships between 2 entities using a different entity manager
Because the entities cannot be tied directly, you must hook into the postLoad event to set up the reference, while persisting the id manually. See docs for an example and explanation of blending a MongoDB object with an ORM object.
Here's a skeleton (getters/setters removed), using 2 entity managers:
Entities:
<?php
// src/My/Bundle1/Entity/Bundle1Entity.php
namespace My\Bundle1\Entity;
class MyBundle1Entity
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
}
// src/My/Bundle2/Entity/Bundle2Entity.php
namespace My\Bundle2\Entity;
class MyBundle2Entity
{
/**
* @var integer
*
* @ORM\Column(name="id", type="integer", nullable=false)
* @ORM\Id
* @ORM\GeneratedValue(strategy="IDENTITY")
*/
private $id;
/**
* @var integer
*
* @ORM\Column(type="integer")
*/
private $myBundle1EntityId;
/**
* @var MyBundle1Entity
*/
private $myBundle1Entity;
public function setMyBundle1Entity($entity)
{
$this->myBundle1EntityId = $entity->getId();
$this->myBundle1Entity = $entity;
}
}
Event Listener:
<?php
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\Event\LifecycleEventArgs;
class MyEventSubscriber
{
public function __construct(EntityManager $bundle1Em)
{
$this->bundle1Em = $bundle1Em;
}
public function postLoad(LifecycleEventArgs $eventArgs)
{
$myBundle2Entity = $eventArgs->getEntity();
$defaultEm = $eventArgs->getEntityManager();
$myBundle2EntityReflProp = $defaultEm->getClassMetadata('Entity\MyBundle2Entity')
->reflClass->getProperty('myBundle1Entity');
$myBundle2EntityReflProp->setAccessible(true);
$myBundle2EntityReflProp->setValue(
$myBundle1Entity, $this->bundle1Em->getReference('Entity\MyBundle1Entity', $myBundle2Entity->getMyBundle1Id())
);
}
}
Obviously, you'd have to register the event listener and pass bundle 1's entity manager as an argument.
这篇关于Symfony2 - Doctrine2:跨数据库连接列抛出映射异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!