如何在具有不同关系的多个捆绑包之间共享实体?
例如,ZooAnimalBundle和FarmAnimalBundle都需要用户实体。第三个Bundle AccountUserBundle具有用户实体。
在Zoo和Farm AnimalBundles中,我创建了一个用户实体,如下所示:
Select * FROM [Backbone_ASPIDER].[dbo].[vw_CFGsvr_Con]
WHERE [Backbone_ASPIDER].[dbo].[vw_CFGsvr_Con].[NodeName] = 'Database' AND [Backbone_ASPIDER].[dbo].[vw_CFGsvr_Con].[EnvironmentName] IS NOT NULL
ORDER BY [Backbone_ASPIDER].[dbo].[vw_CFGsvr_Con].[EnvironmentName] asc
然后我在动物园里有一个医院实体:
use Account\UserBundle\Entity\User as BaseUser;
class User extends BaseUser
{
}
Farm中的Room实体:
class Hospital {
/**
* @ORM\ManyToMany(targetEntity="Zoo\AnaimalBundle\Entity\User")
* @ORM\JoinTable(name="users_zoo_animals")
*/
protected $users;
到目前为止一切正常,我可以调用Zoo.Room-> getUsers()或Farm.Hospital-> getUsers()
但问题是我不确定如何在各自的用户实体中设置反向关系。
例如,如果我更新FarmAnimal用户实体并运行doctrine:generate:entities
class Room {
/**
* @ORM\ManyToMany(targetEntity="Farm\AnaimalBundle\Entity\User")
* @ORM\JoinTable(name="users_farm_animals")
*/
protected $users;
它将从BaseUser复制受保护的$属性并创建所有不是我想要的set和get方法。建立这些关系的正确方法是什么?
更新
如果您没有设置反向关系,您将如何选择hospital.id = 1
的所有用户?/**
* @ORM\Entity
*/
class User extends BaseUser
{
/**
* @ORM\ManyToMany(targetEntity="Room", mappedBy="users", cascade={"persist"})
*/
protected $rooms;
}
这给出了错误:
$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);
我知道我可以从医院中选择并加入用户,因为该关系确实存在,但我需要选择用户,因为我使用它们与Doctrine \ ORM \ Tools \ Pagination \ Paginator
查询将是
Class Account\UserBundle\Entity\User has no association named hospitals
问题是Paginator只看到一个结果医院,因为用户已附加到它。
答案 0 :(得分:3)
您可以定义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
节点,你必须扩展它。)
这不是一个完美的解决方案,因为你无法真正说明用户实体应该拥有哪些字段。另一方面,它是严格的OOP,因为您不必了解User
实现的内部 - 您只需要它来返回正确的值。
答案 1 :(得分:0)
创建帐户的多个定义是错误的方法,除非你想创建3个单独的用户表(即使那样最好不要这样做)。
您真的希望其他实体映射到帐户包中的用户实体。
即,
class Hospital {
/**
* @ORM\ManyToMany(targetEntity="Zoo\AccountBundle\Entity\User")
*/
protected $users;
现在,无需创建反向关系。事实上,这是一种不好的做法,因为你有双向依赖。用户不了解医院,但医院知道它的用户。现在,任何bundle都可以映射到用户实体并重用它。