Учение ОРМ об условной ассоциации - PullRequest
3 голосов
/ 09 июля 2011

Я создаю сайт вопросов и ответов, и мои вопросы, ответы и комментарии находятся в одной таблице posts. Но их postType отличается. Я могу получить ответы на вопрос и комментарии для ответа с этой ассоциацией:

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

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

Но я думаю, что это неправильный способ сделать это, потому что если я получаю вопрос, ответы и комментарии заполняются только ответами. Я должен установить условие для отношения, как postType = 1

Как я могу это сделать?

Ответы [ 2 ]

8 голосов
/ 09 июля 2011

Ваша схема неверна. У вас должно быть два разных объекта для ответов и комментариев, поскольку это две разные вещи, даже если они имеют общий интерфейс.

Вы должны создать две сущности Answer и Comment и создать с ними ассоциации. Поскольку это почти одно и то же, вы можете создать абстрактный класс 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 можно узнать на страницах документации: Отображение наследования

4 голосов
/ 26 ноября 2014

Используйте Doctrine's Критерии фильтрации коллекций класса . Вы даже можете отфильтровать коллекцию перед запросом 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);
    }
...