Сложные предложения WHERE, использующие ORM PHP Doctrine ORM
Я использую ORM PHP Doctrine для создания моих запросов. Однако я не могу представить, как написать следующее предложение WHERE с использованием DQL (Doctrine Query Language):
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
который из-за порядка операций не возвращает ожидаемые результаты.
Кроме того, существует ли разница между методами "where", "и где" и "addWhere"?
UPDATE
Ок, похоже, вы не можете выполнять сложные запросы с помощью 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)");
Ответы
Ответ 1
По моему опыту, каждая сложная функция where
сгруппирована в круглые скобки (я использую Doctrine 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
Правильный способ сделать это можно найти в doctrine 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);
Ответ 3
Похоже, что вы не можете выполнять сложные запросы с помощью DQL, я написал следующий SQL для перехода к методу andWhere():
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause) AND TRUE");
Обратите внимание на "И ИСТИННО", взломать так, чтобы синтаксический анализатор не игнорировал внешние круглые скобки.
Ответ 4
и где можно суммировать как:
Ранее добавленное условие (-ы) Aware WHERE Statement
Вы можете безопасно использовать и Where на месте , где. (он вводит очень малые накладные расходы, что указано ниже во втором элементе списка.)
Реализация 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);
}
который можно прочитать как
- Параметры процесса
- добавить команду AND в ту часть запроса, , если другой, где оператор был добавлен до
- добавить условие
Ответ 5
Что касается разницы между where, andwhere и addwhere, я не думаю, что есть существенное отличие от последнего раза, когда я читаю источник. Однако я бы рекомендовал вам прочитать источник Доктрины. Это очень просто и помогает заполнить отверстия в документации (их много). Что касается сложного выражения, я сам это задавал, но пока не нуждался в нем.
Ответ 6
По моему опыту, я иногда видел разницу между:
$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 строках, второе - только на одном. Я не верил, но есть РАЗЛИЧИЯ!
Ответ 7
$q->andWhere("category1 IN ( $subcategory_in_clause )
OR category2 IN ( $subcategory_in_clause )
OR category3 IN ( $subcategory_in_clause )");
Не могли бы вы попробовать этот вариант, не уверен, что он работает, но стоит попробовать