Symfony2 - 在具有不同关系的 Bundle 之间共享实体

标签 symfony doctrine-orm

您如何在具有不同关系的多个捆绑包之间共享一个实体?

例如 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/

相关文章:

doctrine-orm - DDD、Doctrine2、聚合和 ArrayCollection : how to isolate the domain model?

Symfony2 - 查询生成器多个 orderBy

php - 如何保存 Doctrine2 实体

PHP 和 Elasticsearch 在返回的对象中包含分数/相关性

java - 适合 Java 的命令行解析和执行

php - Doctrine 2.1.5 setFirstResult() 在 MySQL 5.5 中产生错误

symfony - 是否可以在 postPersist 中刷新?

php - Symfony CMF Media Bundle 使图像无效;前端不重新加载缓存图像

php - 防火墙 "secured_area"的 Symfony InvalidConfigurationException

php - Symfony getter 和 setter 生成 - 如何忽略属性