开发者

Doctrine ORM Conditional Association

开发者 https://www.devze.com 2023-03-19 13:31 出处:网络
i\'m building a Q&A site and my questions, answers and comments are on the same posts table. But their postType is different. I can get answers for a question and comments for an answer with this

i'm building a Q&A site and my questions, answers and comments are on the same posts table. But their postType is different. I can get answers for a question and comments for an answer with this association:

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

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

But i think this is not the correct way to do this because if i fetch a question both answers and comments are fi开发者_开发百科lling with just answers. I have to set a condition for relation like postType = 1

How can i do this?


Your schema is invalid. You schould have two different objects for answers and comments as they are two different things, even if they share a common interface.

You should create two entities, Answer and Comment and create assocations to them. As they are almost the same thing you could create an abstract class, AbstractContent, that defines all required fields and accessor methods. Doctrine supports inheritance so the final database schema will be exactly the same, but your OO model will be correct.

/** 
 * @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;

You can read more about inheritance in Doctrine on its documentation pages: Inheritance Mapping


Use Doctrine's Filtering Collections Criteria class. You can even filter the collection first before the sql query:

If the collection has not been loaded from the database yet, the filtering API can work on the SQL level to make optimized access to large collections.

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);
    }
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号