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;
{% for category in categories %}
{% for post in category.posts %}
{% for comment in post.comments %}
{{ comment.content }}
{% endfor %}
{% endfor %}
{% endfor %}
{% for category in categories %}
{% for post in category.lastPosts %}
{% for comment in post.lastComments %}
{{ comment.content }}
{% endfor %}
{% endfor %}
{% endfor %}
SELECT *.p FROM 'post'.'p' WHERE 'p'.'category_id' IN (2, 3, 5, 7, 9) ORDER BY id DESC LIMIT 20;
вы можете получить посты только из одной категории. Так и задумано?
$query = $em->createQuery('SELECT p FROM AppBundle\Entity\Post p WHERE p.category_id IN (?1) ORDER BY p.id DESC');
$query->setMaxResults(20);
$query->setParameter(1, $categoriesIds);
$posts = $query->getResult();
тот запрос, что вы привели имеет такой же недостаток :) Если вы хотите сделать одним запросом, то тут нужны пользовательские переменные. И сомневаюсь, что доктрина так умеет
{% for category in categories %} {% for post in category.lastPosts %} {% for comment in post.lastComments %} {{ comment.content }} {% endfor %} {% endfor %} {% endfor %}
public function getLatestPosts()
{
$collection = $this->getPosts();
$criteria = Criteria::create()
->orderBy(["id" => Criteria::DESC])
->setFirstResult(0)
->setMaxResults(20);
return $collection->matching($criteria);
}
You can move the access of slices of collections into dedicated methods of an entity. For example Group#getTodaysBirthdayUsers()
Что, если у меня добавятся параметры, например направление сортировки или максимальное кол-во измениться?
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();
}
The process of hydration becomes extremely expensive when more than 2 LEFT JOIN operations clauses are part of our queries:
Кроме того я не уверен, что вы понимаете суть гидратации.
Если вы желаете ИЗВЛЕКАТЬ данные из БД и выводить их "in View" в виде неких списков - то гидратация вам не нужна.
$entityManager = $this->getServiceManager()->get('Doctrine\ORM\EntityManager');
$categoryRepository = $entityManager->getRepository('Database\Entity\Category');
$testCategories = $categoryRepository->findAll();
$viewModel->setVariables(['testCategories' => $testCategories]);
<ol>
{% for testCategory in testCategories %}
<li>
{{ testCategory.getShortName() }}
<ol>
{% for categoryHasProduct in testCategory.getCategoryHasProducts() %}
<li>
{{ categoryHasProduct.getProduct().getShortName() }}
</li>
{% endfor %}
</ol>
</li>
{% endfor %}
</ol>
пишите разработчикам Doctrine...
конечно создается огромное количество запросов к БД, но по другому и не выбрать такую коллекцию данных (пользовательские переменные не в счет, в постгресе например их вовсе нет). Теперь я вот думаю, а это нормально иметь такие методы в entity:
В репозитории сущности Category создаете метод типа getCategory, где создаете подобный запрос.
Вот только сортировка и количество разных под-коллекций одним запросом не получится.
Как вариант - потом делать пагинацию и фильтрацию полученного результата.
То есть вот такое решение с миллионом запросов в БД лучше одного запроса с join?
Вот какой ответ - решил принять за правильный liongen благодаря вашим советам.
Любой школьник сможет так решить проблему - максимально увеличив количество запросов
Therefore, the simplest yet most limiting advice is to avoid collection-valued associations whenever they are not strictly necessary.
... и избыточном извлечении таких связей Doctrine.
... но что в замен - куча избыточного запутанного кода, результат которого еще труднее связать вместе.