13

我很难找到一种方法来使用 Doctrine2 作为 ORM 在 Symfony2 中的包之间适当地扩展实体。

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

我有两个 Bundle:UserBundle 和 BlogBu​​ndle。我希望能够在没有 BlogBu​​ndle 的项目中使用 UserBundle,但 BlogBu​​ndle 将始终用于具有 User Bundle 的项目中。如果 BlogBu​​ndle 依赖于 UserBundle 是可以的,但反之则不然。

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

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

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

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

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

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

用户捆绑\实体\用户

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

BlogBu​​ndle\Entity\Post

@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 中定义。如果没有来自控制器的对该对象的任何引用,则不会访问数据库。由于扩展对象没有持久化任何内容,除非我尝试从控制台更新数据库模式。

我可以使用单向关系,但这限制了我从控制器内访问数据的方式。

4

2 回答 2

8

您可以在此链接中查看有关继承的信息: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
{
    ....
}

祝你好运!

于 2012-10-17T09:09:55.987 回答
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 ...

于 2015-05-12T16:50:33.240 回答