您如何在具有不同关系的多个捆绑包之间共享一个实体?
例如 ZooAnimalBundle 和 FarmAnimalBundle 都需要一个用户实体。第三个捆绑 AccountUserBundle 具有用户实体。
在 Zoo 和 Farm AnimalBundles 中,我创建了一个用户实体,如下所示:
use Account\UserBundle\Entity\User as BaseUser;
class User extends BaseUser
{
}
然后我在动物园有一个 Hospital 实体:
class Hospital {
/**
* @ORM\ManyToMany(targetEntity="Zoo\AnaimalBundle\Entity\User")
* @ORM\JoinTable(name="users_zoo_animals")
*/
protected $users;
以及 Farm 中的 Room 实体:
class Room {
/**
* @ORM\ManyToMany(targetEntity="Farm\AnaimalBundle\Entity\User")
* @ORM\JoinTable(name="users_farm_animals")
*/
protected $users;
到目前为止一切正常,我可以调用 Zoo.Room->getUsers() 或 Farm.Hospital->getUsers()
但是问题是我不确定如何在各自的 User 实体中设置反向关系。
例如,如果我更新 FarmAnimal 用户实体并运行学说:生成:实体
/**
* @ORM\Entity
*/
class User extends BaseUser
{
/**
* @ORM\ManyToMany(targetEntity="Room", mappedBy="users", cascade={"persist"})
*/
protected $rooms;
}
它将从 BaseUser 复制 protected $properties 并创建所有 set 和 get 方法,这不是我想要的。建立这些关系的正确方法是什么?
更新
如果不设置逆向关系,如何选择hospital.id = 1的所有用户
$qb = $this->getEntityManager()->createQueryBuilder()
->select(
'u'
)
->from('Account\UserBundle\Entity\User','u')
->leftJoin('u.hospitals', 'h')
->andWhere('h.id = :hospital_id')
->setParameter('hospital_id',$hospital_id);
这给出了错误:
Class Account\UserBundle\Entity\User has no association named hospitals
我知道我可以从医院中选择并加入用户,因为这种关系确实存在,但我需要选择用户,因为我将它们与 Doctrine\ORM\Tools\Pagination\Paginator 一起使用
查询将是
$qb = $this->createQueryBuilder('a')
->select(
'h', 'u'
)
->leftJoin('h.users', 'u')
问题是 Paginator 只能看到一个结果 Hospital,因为用户已附加到它。
最佳答案
您可以定义 abstract entity dependencies并用其他包实现它们。
首先,每个依赖于用户实体的包都应该定义一个用户界面。例如:
namespace Foo\BarBundle\Entity;
interface UserInterface
{
public function getId();
public function getEmail();
// other getters
}
然后,在取决于用户的每个实体中,定义关系,例如:
namespace Foo\BarBundle\Entity;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\Validator\Constraints as Assert;
/**
* @ORM\Entity
*/
class Something
{
/**
* @ORM\ManyToOne(targetEntity="UserInterface")
* @Assert\NotNull
*/
protected $User;
// add other fields as required
}
现在您需要将 User 实体注册为 UserInterfaces 的实现:
namespace Foo\UserBundle\Entity;
use Foo\BarBundle\Entity\UserInterface as BarUserInterface;
use Foo\FoobarBundle\Entity\UserInterface as FoobarUserInterface;
/**
* @ORM\Entity
*/
class User implements BarUserInterface, FoobarUserInterface
{
// implement the demanded methods
}
然后将以下内容添加到
app/config/config.yml
:doctrine:
orm:
resolve_target_entities:
Foo\BarBundle\Entity\UserInterface: Foo\UserBundle\Entity\User
Foo\FooarBundle\Entity\UserInterface: Foo\UserBundle\Entity\User
(注意:通常已经有一个
doctrine.orm
节点,您必须对其进行扩展。)这不是一个完美的解决方案,因为您无法真正说出用户实体应该具有哪些字段。另一方面,它是严格的面向对象编程,因为您不必了解
User
的内部结构实现——你只需要它来返回正确的值。
关于Symfony2 - 在具有不同关系的 Bundle 之间共享实体,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30650688/