Один из способов решить эту проблему - использовать extra объединение без отношения :
$query = $this->createQueryBuilder('ad')
->select('ad.id, ad.title, ad.year, ad.hours, ad.status')
->addSelect('rem.remark')
->leftJoin('ad.remark', 'rem', Join::WITH, "rem.language = 'NL' OR rem.language = 'EN'")
->leftJoin(Remark::class, 'customRem', Join::WITH,
"rem.id <> customRem.id
AND rem.ad = customRem.ad
AND customRem.language = 'NL'")
->where('customRem.id IS NULL')
->getQuery()
->getResult();
Идея
- если для объявления существует примечание на языке NL, добавьте это примечание, присоединенное к каждой строке результата этого объявления, ожидайте для себя (будет нулевым)
- если примечание на языке NL не существует и существует EN, то присоединенная строкабудет нулевым
Наконец, условие customRem.id IS NULL
делает эту работу.
Решение на нескольких языках
В случае 3 поддерживаемыхязыки, потому что DE> EN> NL , вы можете сделать:
->leftJoin(Remark::class, 'customRem', Join::WITH,
"rem.id <> customRem.id AND rem.ad =
customRem.ad AND rem.language < customRem.language")
Для нескольких языков и предположить, что " custom * " возможность заказать языки, выможно использовать:
"rem.id <> customRem.id
AND rem.ad = customRem.ad AND
(case when rem.language = 'NL' THEN 3 " .
"when rem.language = 'EN' THEN 2 " .
"when rem.language = 'DE' THEN 1 ELSE 0 END) < (case when customRem.language = 'NL' THEN 3 " .
"when customRem.language = 'EN' THEN 2 " .
"when customRem.language = 'DE' THEN 1 ELSE 0 END)"
В качестве альтернативы, вы можете создать таблицу "lang_position" (id, language, position) и дважды присоединиться, чтобы получить позицию из языка.