@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...
Но чувствую, что это скорее крик безысходности.
  • Вопрос задан
  • 1223 просмотра
Решения вопроса 1
BoShurik
@BoShurik Куратор тега Symfony
Symfony developer
Если я правильно понял вопрос
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();
}
Ответ написан
Ваш ответ на вопрос

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

Войти через центр авторизации
Похожие вопросы