【问题标题】:Extending entities in Symfony2 with Doctrine2使用 Doctrine2 扩展 Symfony2 中的实体
【发布时间】:2012-09-29 22:15:44
【问题描述】:

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

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

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

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

关系: 用户和博客文章之间需要存在一对多的关系。这是通过 BlogBu​​ndle\Entity\Post 对象(表)上的 Author_ID 属性(列)实现的,该对象映射到 UserBundle\Entity\User.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 学说:模式:更新 --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\Entity\User

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

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

【问题讨论】:

  • 我知道这是一个非常古老的问题;但你有没有解决过?我也面临同样的问题,正在努力寻找任何可行的解决方案。

标签: symfony doctrine-orm entities extending


【解决方案1】:

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

祝你好运!

【讨论】:

  • 我认为这不是一个令人满意的解决方案,因为在 @DiscriminatorMap 中有从 UserBundle 到 BlogBu​​ndle 的引用。我会对 UserBundle 对 BlogBu​​ndle 没有引用/依赖关系的解决方案感兴趣。
【解决方案2】:

我想你会觉得这个捆绑包很有趣:

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...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多