使用Doctrine2在Symfony2中扩展实体

时间:2012-10-09 14:37:32

标签: symfony doctrine-orm entities extending

我很难找到一种方法,使用Doctrine2作为ORM,在Symfony2中的捆绑中适当地扩展实体。

目前,我发现有三种方法可以使用Doctrine2作为ORM在Symfony2中扩展实体。 Mapped SuperclassSingle Table InheritanceClass Table Inheritance。这些都不适用于我想要做的事情。

我有两个捆绑包:UserBundle和BlogBu​​ndle。我希望能够在没有BlogBu​​ndle的项目中使用UserBundle,但BlogBu​​ndle将始终用于具有User Bundle的项目中。如果BlogBu​​ndle依赖于UserBundle,那就没关系,但不是相反。

我有两个实体: BlogBu​​ndle \ Entity \ Post和 UserBundle \实体\用户

关系: 用户和博客帖子之间需要有一对多的关系。这是通过BlogBu​​ndle \ Entity \ Post对象(表)上的Author_ID属性(列)实现的,该对象映射到UserBundle \ Entity \ User.id

问题: 我可以直接从BlogBu​​ndle中调用UserBundle \ Entity \ User实体,并使用Uni-Directional映射实现我正在寻找的东西。这不允许我从User对象中访问用户的所有帖子。我可以通过自定义查询访问数据,但这不像用户通过用户对象访问帖子那样干净。

我想要做的是从BlogBu​​ndle中扩展UserBundle \ Entity \ User对象,并将方法和属性添加到此对象中,以建立BlogBu​​ndle中使用的一对多映射。这些都没有持久化,它只是定义了关系,并允许我逻辑上访问用户在实现BlogBu​​ndle和UserBundle的应用程序中创建的所有帖子,方法是向博客包中的User对象添加所需的功能(从而避免依赖从UserBundle到BlogBu​​ndle)。

当我创建BlogBu​​ndle \ Entity \ User对象并扩展UserBundle \ Entity \ User时,我必须声明@ORM \ Table(name =“usertablename”)。如果不这样做,任何访问BlogBu​​ndle \ Entity \ User对象的尝试都将无法访问数据库。由于扩展对象中没有任何添加内容持续存在,因此在捆绑包中可以正常工作。这个问题是当我调用“php app / console doctrine:schema:update --force”时,由于两个实体试图映射到&创建相同的表。我已经尝试使用最近实现的ResolveTargetEntityListener功能,但是这与Mapped Superclas,STI和CTI一起强制从UserBundle强制依赖BlogBu​​ndle。

以下是我的对象,以帮助说明我的设置。它们的缩写是为了清楚起见。我意识到一些语义不正确,但它的目的是传达思想和方法。配置。

UserBundle \实体\用户

@ORM\Table(name="app_user")
@ORM\Entity
class User implements UserInterface
{
    ...
}

BlogBu​​ndle \实体\邮

@ORM\Table(name="app_post")
@ORM\Entity
class Post
{
    ...

    @ORM\Column(name="author_id", type="integer")
    protected $author_id;

    @ORM\ManyToOne(targetEntity="\App\BlogBundle\Entity\User", inversedBy="posts")
    @ORM\JoinColumn(name="author_id", referencedColumnName="id")
    protected $author;
}

BlogBu​​ndle \实体\用户

use App\UserBundle\Entity\User as BaseUser
@ORM\Entity
@ORM\table(name="app_user")
class User extends BaseUser
{
    ....

    @ORM\OneToMany(targetEntity="App\BlogBundle\Entity\Post", mappedBy="author")
    protected $posts;

    public function __construct()
    {
        parent::_construct();

        $this->posts = new \Doctrine\Common\Collections\ArrayCollection();
    }

    .... 
    /* Getters & Setters, nothing that defines @ORM\Column, nothing persisted */
}

这有效,但问题是我将项目中的两个实体映射到同一个表。扩展对象不从它的父级获取@ORM \ Table(name =“app_user”),因此必须在BlogBu​​ndle \ Entity \ User中定义它。如果没有来自控制器的任何对此对象的引用将不访问数据库。由于扩展对象中没有任何内容,因此除了我尝试从控制台更新数据库模式时,没有任何内容被破坏。

我可以使用单向关系,但这限制了我如何从控制器中访问数据。

2 个答案:

答案 0 :(得分:7)

您可以在此链接中查看有关继承的信息:http://docs.doctrine-project.org/en/latest/reference/inheritance-mapping.html#single-table-inheritance

您必须在UserBundle \ Entity \ User:

中声明
/**
 * @Entity
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(name="discr", type="string")
 * @DiscriminatorMap({"baseuser" = "UserBundle\Entity\User", "blogUser" = "BlogBundle\Entity\User"})
 */
class User implements UserInterface
{
    ...
}

BlogBu​​ndle \ Entity \ User

use App\UserBundle\Entity\User as BaseUser;
/**
 * @ORM\Entity
 */
class User extends BaseUser
{
    ....
}

古德勒克!

答案 1 :(得分:0)

我认为你会发现这个Bundle很有趣:

https://github.com/mmoreram/SimpleDoctrineMapping

它允许您通过参数定义哪些文件映射您的实体,允许覆盖您的通用包的每个实体。

例如:

parameters:

    #
    # Mapping information
    #
    test_bundle.entity.user.class: "TestBundle\Entity\User"
    test_bundle.entity.user.mapping_file_path: "@TestBundle/Mapping/Class.orm.yml"
    test_bundle.entity.user.entity_manager: default
    test_bundle.entity.user.enable: true

我看到的唯一反对意见是你必须以同样的方式定义所有下一个实体,因为你禁用了auto_mapping ...