【问题标题】:How to capture external attributes on a Doctrine entity如何捕获 Doctrine 实体的外部属性
【发布时间】:2014-05-14 19:35:12
【问题描述】:

在我的应用程序中,我有用户可以阅读的帖子。我想捕捉这种状态,但我被困在如何通过实体结构和关系来实现这一点。

我的想法是拥有一个 User 和 Post 实体并捕获阅读状态以使用看起来像这样的 PostMeta 实体:

class PostMeta {
   /** @ORM\OneToOne(targetEntity="User")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id") */
   protected $user;

   /** @ORM\ManyToOne(targetEntity="Post", inversedBy="meta") */
   protected $post;

   /** @ORM\Column(name="is_read", type="boolean") */
   protected $isRead;
}

PostMeta 将始终与用户保持 OneToOne 关系,因为它只能属于单个用户。但是,它会与 Post 具有 ManyToOne 关系,因为许多用户可以拥有同一个 Post 的 PostMeta。

要加载实际的 PostMeta,Post 将有一个 $meta 属性,可以将 PostMeta 加载到该属性中。因此,帖子只会加载特定用户:

class Post {
   /** @ORM\ManyToMany(targetEntity="User", mappedBy="posts") */
   protected $users;

   /** @ORM\OneToMany(targetEntity="PostMeta", mappedBy="posts") */
   protected $meta;
}

有两件事我被困在:

  1. 这是解决此问题的好方法吗?
  2. 如何编写 DQL 来检索此信息,记住当用户 由于 PostMeta 仅在用户已阅读帖子时创建,所以还没有阅读帖子,因此不会有 PostMeta 条目。

【问题讨论】:

  • PostMeta 中的 isRead 字段似乎是多余的
  • 那么你建议我在哪里跟踪这个状态?将来我可能会添加其他状态,例如已加星标。

标签: php doctrine-orm entity-relationship dql


【解决方案1】:

为什么不创建ManyToMany 关系?:

/**
 * @ORM\ManyToMany(targetEntity="Post")
 */
 protected $readPosts;

这样您就可以获得所需的数据,而无需添加额外的冗余isRead 字段。当然,这仅在您只有一个“元数据”要跟踪时才有效。当你有更多的时候,你需要做你现在正在做的事情,这基本上是一个手动的ManyToMany 关系。

要知道用户是否阅读了给定的帖子,您可以直接在您的实体中进行:

public hasRead(Post $post)
{
    for($this->getReadPosts() as $post)
    {
        if($post === $post)
            return true;
    }

    return false;
}

此外,您可以使用 DQL 选择哪些用户已阅读给定帖子,例如:

SELECT u FROM MyBundle:User u JOIN u.readPosts rp WHERE rp = :post

【讨论】:

  • 这是一个有趣的想法。我可以对任何其他类型的属性做同样的事情。我要试试这个。
猜你喜欢
  • 2023-03-05
  • 1970-01-01
  • 2014-06-06
  • 2021-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多