@Byte255
Пишу на PHP за еду

Symfony 3 — 5, Doctrine 2. Возможно ли используя Criteria выбрать данные из связанных таблиц одним запросом?

Здравствуйте!

Есть таблица объявлений и таблица пользователей, которые эти объявления подали.
При выводе списка объявлений надо показывать имена пользователей.

То есть хочется чтобы выполнился запрос вида

SELECT adverts.title, adverts.body, users.name 
FROM adverts 
LEFT JOIN users ON users.id = adverts.user_id


Не могу понять, возможно ли сделать это с помощью аннотаций OneToMany и ManyToOne используя Criteria

У меня сейчас так:

Фрагмент сушности Adverts
/**
	 * @var Users
	 * @ORM\ManyToOne(targetEntity="Users", inversedBy="advertsByUserId")
	 * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
	*/
	private $userObject;


Фрагмент сушности Users

/**
     * @var array of Adverts
     * @ORM\OneToMany(targetEntity="Adverts", mappedBy="userObject")
    */
    protected $advertsByUserId;


Фрагмент контроллера
/**
 * 
 * @param string $sRegion = '' код региона латинскими буквами
 * @param string $sCity = ''   код города латинскими буквами
 * @return array
*/
private function _loadAdvList(string $sRegion = '', string $sCity = '', Request $oRequest) : array 
{
	$limit = $this->getParameter('app.records_per_page', 10);
	$repository = $this->getDoctrine()->getRepository('App:Adverts');
	
	$oCriteria = Criteria::create();
	$e = Criteria::expr();
	$oCriteria->where( $e->eq('isDeleted', 0) )
		->andWhere( $e->eq('isHide', 0) )
		->andWhere( $e->eq('isModerate', 1) )
		->orderBy(['delta' => Criteria::DESC])
		->setMaxResults($limit)
		->setFirstResult(0);
	

	//тут ещё разные фильтры по полям Adverts устанавливаются,
    // думаю в контексте вопроса не принципиально, вырезал
	
	
	$aCollection = $repository->matching($oCriteria)->toArray();
	return $aCollection;
}


Фрагмент view

<div class="name">
		{% if (item.userObject) %}
			{{ item.userObject.displayName }}
		{% else %}
			{{ item.id }}
		{% endif %}
	</div>


В итоге имеем
1 Запрос в таблицу adverts и
10 SQL запросов в таблицу users, по одному на каждое объявление

Я понимаю, как это можно сделать одним запросом используя queryBuilder, но возможно ли добиться выборки одним запросом используя Criteria?
  • Вопрос задан
  • 854 просмотра
Решения вопроса 1
@Flying
Criteria - это просто возможность сформировать какое-то относительно сложное условие для QueryBuilder, не более того.

Вам необходимо определиться с тем что именно вы хотите сделать:
  • Если вы хотите выбрать данные из связанных таблиц - то это можно сделать через QueryBuilder с гидрацией, к примеру, в массив. В этом случае запрос будет ровно один - тот что вы запускаете
  • Если вы хотите выбрать entities - то логика этих выборок определяется UnitOfWork и в общем может как приводить к 10 запросам так и не приводить в зависимости от содержимого identity map. Т.е., условно говоря, если бы связанные entities уже были бы в identity map - повторной выборки бы не происходило. Также выборки бы не происходило если бы вы обращались к identity полю связанной entity. Однако вы запрашиваете данные из связанной entity, причём делаете это раздельно для каждого entity, почему же вы ожидаете что Doctrine не полезет в базу за этими данными?
Ответ написан
Пригласить эксперта
Ваш ответ на вопрос

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

Похожие вопросы