Doctrine ORM 条件关联

4

我正在建立一个问答网站,我的问题、回答和评论都在同一个posts表中。但它们的postType不同。我可以通过这个关联来获取问题的答案和回答的评论:

/**
 * @OneToMany(targetEntity="Cms\Entity\Post", mappedBy="parent")
 */
private $answers;

/**
 * @OneToMany(targetEntity="Cms\Entity\Post", mappedBy="parent")
 */
private $comments;

但我认为这不是正确的做法,因为如果我获取一个问题,它的回答和评论都会被填充为回答。我需要为关系设置一个条件,如 postType = 1

我该怎么做?

2个回答

10

你的模式不合法。你应该为答案和评论创建两个不同的对象,因为它们是两个不同的事物,即使它们共享一个公共接口。

你应该创建两个实体,AnswerComment,并为它们创建关联。由于它们几乎是相同的东西,因此可以创建一个抽象类AbstractContent,定义所有必需的字段和访问器方法。Doctrine支持继承,因此最终的数据库模式将完全相同,但你的面向对象模型将是正确的。

/** 
 * @MappedSuperclass 
 * @InheritanceType("SINGLE_TABLE")
 * @DiscriminatorColumn(type = "string", name = "discriminator")
 * @DiscriminatorMap({ "answer" = "Answer", "comment" = "Comment" })
 */
abstract class AbstractContent {
    /** @Column(type = "integer") @Id @GeneratedValue("AUTO") */
    protected $id;

    /** @Column(type="text") */
    protected $content;

    /** @Column(type = "datetime", name = "created_at") */
    protected $createdAt;

    public function __construct() {
        $this->createdAt = new \DateTime();
    }
}

/** @Entity */
class Answer extends AbstractContent { }

/** @Entity */
class Comment extends AbstractContent { }

/**
 * @OneToMany(targetEntity="Cms\Entity\Answer", mappedBy="parent")
 */
private $answers;

/**
 * @OneToMany(targetEntity="Cms\Entity\Comment", mappedBy="parent")
 */
private $comments;

您可以在Doctrine的文档页面中了解有关继承的更多信息:继承映射


你的超类中缺少 "@Entity" 或 "@ORM\Entity" 注解。除此之外,答案是正确的。 - Siwei
@Siwei AbstractContent本身不是一个实体,因此不应该有@Entity注释。请查看文档中的示例;-) - Crozin
1
也许这是一个Doctrine版本的问题,但在最新的Doctrine 2 ORM(截至2014年12月20日),<code>@Entity</code>标签需要包含在超类中,否则它会报错“不支持在映射的超类上定义继承信息”。 - Siwei

4
使用Doctrine的过滤集合条件类。您甚至可以在SQL查询之前先过滤集合:
如果尚未从数据库加载集合,则过滤API可以在SQL级别上工作,以便对大型集合进行优化访问。
use Doctrine\Common\Collections\Collection;
use Doctrine\Common\Collections\Criteria;

...

    /** @var Collection */
    protected $posts;

    /**
     * @return Post[]
     */
    public function getAnswers()
    {
        $criteria = Criteria::create()
            ->where(Criteria::expr()->eq('postType', 'answer'))
        ;

        return $this->posts->matching($criteria);
    }

    /**
     * @return Post[]
     */
    public function getComments()
    {
        $criteria = Criteria::create()
            ->where(Criteria::expr()->eq('postType', 'comment'))
        ;

        return $this->posts->matching($criteria);
    }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接