Сложные предложения WHERE с использованием доктрины PHP ORM
Я использую доктрину PHP ORM для создания моих запросов. Однако я не могу понять, как написать следующее предложение WHERE с помощью DQL (язык запросов доктрины):
WHERE name='ABC' AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X')
AND price > 10
как я могу указать, куда идут круглые скобки?
то, что у меня в настоящее время есть в моем PHP-коде, это:
->where('name = ?', 'ABC')
->andWhere('category1 = ?', 'X')
->orWhere('category2 = ?', 'X')
->orWhere('category3 = ?', 'X')
->andWhere('price > ?', 10)
но это производит что-то вроде
WHERE name='ABC' AND category1 = 'X' OR category2 = 'X' OR category3 = 'X'
AND price > 10
что, из-за порядка операций, не возвращает ожидаемые результаты.
кроме того, есть разница между методами" где"," и где "и" addWhere"?
обновление Хорошо, похоже, вы не можете выполнять сложные запросы с помощью DQL, поэтому я пытался написать SQL вручную и использовать метод andWhere() для его добавления. Тем не менее, я использую WHERE..IN и Doctrine, похоже, удаляет мои заключительные скобки:
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause)");
6 ответов
из моего опыта, каждый комплекс where
функция сгруппирована в скобках (я использую доктрину 1.2.1).
$q->where('name = ?', 'ABC')
->andWhere('category1 = ? OR category2 = ? OR category3 = ?', array('X', 'X', 'X'))
->andWhere('price < ?', 10)
производит следующий SQL:
WHERE name = 'ABC'
AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X')
AND price < 10
правильный способ сделать это можно найти в доктрина 2-условные запросы построителя запросов... Если заявления? как отметил @Jekis. Вот как использовать построитель выражений для решения этой проблемы, как в Примере @anushr.
$qb->where($qb->expr()->eq('name', ':name'))
->andWhere(
$qb->expr()->orX(
$qb->expr()->eq('category1', ':category1'),
$qb->expr()->eq('category2', ':category2'),
$qb->expr()->eq('category3', ':category3')
)
->andWhere($qb->expr()->lt('price', ':price')
->setParameter('name', 'ABC')
->setParameter('category1', 'X')
->setParameter('category2', 'X')
->setParameter('category3', 'X')
->setParameter('price', 10);
поскольку кажется, что вы не можете выполнять сложные запросы с помощью DQL, я написал следующий SQL для передачи методу andWhere ():
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause) AND TRUE");
обратите внимание на "и TRUE", хак, чтобы парсер не игнорировал внешние круглые скобки.
andWhere можно суммировать как:
ранее добавленные условия(Ы) знают, где оператор
вы можете безопасно использовать andWhere на месте от здесь. (он вводит очень крошечные накладные расходы, которые указаны ниже во 2-м пункте списка.)
реализация andWhere является: (доктрина 1.2.3)
public function andWhere($where, $params = array())
{
if (is_array($params)) {
$this->_params['where'] = array_merge($this->_params['where'], $params);
} else {
$this->_params['where'][] = $params;
}
if ($this->_hasDqlQueryPart('where')) {
$this->_addDqlQueryPart('where', 'AND', true);
}
return $this->_addDqlQueryPart('where', $where, true);
}
где можно прочитать как
- параметры процесс
- добавить и заявление здесь часть запроса, если другой оператор where был добавлен до
- добавить условие
Что касается разницы между where, andwhere и addwhere, я не считаю, что есть существенная разница с последним разом, когда я читал источник. Однако я бы посоветовал вам прочитать источник доктрины. Это очень просто, и помогает заполнить отверстия в документации (их много). Что касается сложных заявлений where, я сам задавался этим вопросом, но пока не нуждался в этом.
по моему опыту, я иногда видел разницу между :
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause)");
и
$q->andWhere("(category1 IN $subcategory_in_clause OR category2 IN $subcategory_in_clause OR category3 IN $subcategory_in_clause)");
первое утверждение написано на 3 строках, второе-только на одной. Я не верил в это, но есть разница !