Doctrine ORM条件协会

时间:2011-07-09 11:08:14

标签: doctrine doctrine-orm one-to-many relation

我正在建立一个Q& A网站,我的问题,答案和评论都在同一个posts表格中。但是他们的postType是不同的。我可以通过这种关联得到问题和答案的答案:

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

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

但我认为这不是正确的方法,因为如果我提问,答案和评论都只是填充答案。我必须为postType = 1

之类的关系设置一个条件

我该怎么做?

2 个答案:

答案 0 :(得分:8)

您的架构无效。你可以有两个不同的答案和评论对象,因为它们是两个不同的东西,即使它们共享一个共同的界面。

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

/** 
 * @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继承的更多信息:Inheritance Mapping

答案 1 :(得分:3)

使用Doctrine的Filtering Collections Criteria class。您甚至可以在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);
    }