2009-06-26 3 views
31

Я использую ORM PHP Doctrine для создания моих запросов. Тем не менее, я не могу достаточно показаться, чтобы выяснить, как написать следующее условие WHERE с использованием DQL (Doctrine Query Language):Сложные предложения WHERE с использованием PHP Doctrine ORM

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»?

UPDATE Хорошо, кажется, что вы не можете делать сложные запросы с использованием DQL, поэтому я пытался писать SQL вручную и использовать метод andWhere(), чтобы добавить его. Тем не менее, я использую WHERE..IN и доктрина, кажется, зачистки мои ограждающих круглые скобки:

$q->andWhere("(category1 IN $subcategory_in_clause 
      OR category2 IN $subcategory_in_clause 
      OR category3 IN $subcategory_in_clause)"); 
+0

Другое решение можно найти здесь http://stackoverflow.com/a/7720723/251735 – Jekis

ответ

60

Из моего опыта каждый комплекс 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 
+0

Именно то, что я искал! –

+0

работал для меня спасибо ..! –

0

Что касается разницы между тем, где, andwhere и addwhere, я не верю, что существует значительная разница с последнего раза я прочитал источник. Однако я бы рекомендовал вам прочитать источник Доктрины. Это очень просто, и помогает заполнять отверстия в документации (их много). Что касается сложных заявлений, я сам это задавал, но пока не нуждался в этом.

1

Как кажется, вы не можете делать сложные запросы с использованием DQL, я написал следующий SQL, чтобы перейти к andWhere() метод:

$q->andWhere("(category1 IN $subcategory_in_clause 
OR category2 IN $subcategory_in_clause 
OR category3 IN $subcategory_in_clause) AND TRUE"); 

Обратите внимание на «И ИСТИНА», хак так, чтобы синтаксический анализатор не будет игнорировать внешние круглые скобки.

+0

Я думаю, что решение anushr является гораздо лучше. Нет взлома и использования подготовленных заявлений. –

1

andWhere можно резюмировать следующим образом:
Ранее добавленные условия (ы) Aware ГДЕ Заявление

Вы можете безопасно использовать andWhere InPlace от , где. (он вводит очень малые накладные расходы, что указано ниже во втором элементе списка.)

Реализация andWhere: (Doctrine 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); 
} 

, который может быть прочитан как,

  1. параметры процесса
  2. добавить И заявление , где часть запроса, если другой, где был добавлен заявление перед
  3. прилагается условие
0

В моем опыте, я иногда видел разницу между:

$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 линии, вторая, только на одном. Я не верил в это, но есть РАЗЛИЧИЯ!

8

Правильный способ сделать это можно найти по адресу doctrine 2 - query builder conditional queries... If statements?, как указано @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); 
+4

Именно поэтому я ненавижу Учение. Это невозможно прочитать и понять. – Nicolas