@liongen

Doctrine2. Как выбрать и гидрировать связанные коллекции?

Есть задача задача следующего вида:

Имеется сущность Category, к которой через связь OneToMany привязана сущность Post, которая в свою очередь, также имеет связь OneToMany с сущностью Comment

Нужно: выбрать 10 категорий, у которых будут содержаться 20 постов отсортированные в обратном порядке по id, у каждой из которых также будут 10 комментов, отсортированные по дате добавления.

Получается всего 3 запроса, что то типа:

SELECT *.c FROM 'category'.'c' ORDER BY id DESC LIMIT 10;
SELECT *.p FROM 'post'.'p' WHERE 'p'.'category_id' IN (2, 3, 5, 7, 9) ORDER BY id DESC LIMIT 20;
SELECT *.c FROM 'comment'.'c' WHERE 'c.'post_id' IN (56, 42, 345, 223, ...) ORDER BY created_at DESC LIMIT 10;


На Yii2/Laravel5 такие задачи решаются автоматически, через ActiveRecord.

Предполагаю, что надо разбить каждый из запросов в отдельный репозиторий (что то вроде findCommentsByPosts($posts = []), но как в итоге это все связать воедино, чтобы, например при рендере в твиге можно было к коллекциям внутри коллекций обращаться:

{% for category in categories %}
    {% for post in category.posts %}
         {% for comment in post.comments %}
              {{ comment.content }}
         {% endfor %}
    {% endfor %}
{% endfor %}


Может, есть лучше способ, как решают такие проблемы в Doctrine2?

Натыкался на решения подобно этому: https://phpclub.ru/talk/threads/doctrine-collectio...
Но чувствую, что это скорее крик безысходности.
  • Вопрос задан
  • 257 просмотров
Решения вопроса 1
BoShurik
@BoShurik
Если я правильно понял вопрос
docs.doctrine-project.org/projects/doctrine-orm/en...
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
@novrm
В репозитории сущности Category создаете метод типа getCategory, где создаете подобный запрос.
Вот только сортировка и количество разных под-коллекций одним запросом не получится.
Как вариант - потом делать пагинацию и фильтрацию полученного результата.

public function getCategory()
{
        $queryBuilder = $this->getEntityManager()->createQueryBuilder();

        $queryBuilder
        ->select('category')->from($this->getClassName(), 'category')
        ->addSelect('c_categoryHasPosts')->leftJoin('category.categoryHasPosts', 'c_categoryHasPosts')
            ->addSelect('c_cHasP_post')->leftJoin('c_categoryHasPosts.post', 'c_cHasP_post')
                ->addSelect('c_cHasP_p_postHasComments')->leftJoin('c_cHasP_post.postHasComments', 'c_cHasP_p_postHasComments')
                    ->addSelect('c_cHasP_p_pHasC_comment')->leftJoin('c_cHasP_p_postHasComments.comment', 'c_cHasP_p_pHasC_comment')
        ->setParameter('categoryId', 1)
        ->setParameter('postId', 1)
        ->andWhere('c_cHasP_post.category_id = :categoryId')
        ->orWhere('c_cHasP_p_pHasC_comment.post_id = :postId')
        
        return $queryBuilder->getQuery()->getResult();
}
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через TM ID
Похожие вопросы
Skyeng Москва
До 180 000 руб.
Skyeng Москва
До 160 000 руб.
WEBINAR Москва
от 120 000 до 160 000 руб.