Сложные предложения WHERE с использованием PHP Doctrine ORM - PullRequest
38 голосов
/ 26 июня 2009

Я использую PHP Doctrine ORM для построения своих запросов. Однако я не могу понять, как написать следующее предложение 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

, который в силу порядка операций не возвращает ожидаемых результатов.

Кроме того, есть ли разница между методами "где", "и где" и "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)");

Ответы [ 7 ]

68 голосов
/ 11 января 2010

Из моего опыта каждая сложная 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
15 голосов
/ 18 августа 2016

Правильный способ сделать это можно найти в доктрина 2 - построитель запросов условных запросов ... If операторов? , как отмечено @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);
1 голос
/ 05 февраля 2011

и где можно суммировать как:
Ранее добавленные условия (ы), Зная WHERE, Заявление

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

Реализация 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. добавить оператор AND к , где часть запроса, , если другой оператор where был добавлен до
  3. добавить условие
1 голос
/ 26 июня 2009

Поскольку кажется, что вы не можете выполнять сложные запросы с использованием 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 голосов
/ 16 мая 2019
$q->andWhere("category1 IN ( $subcategory_in_clause )
              OR category2 IN ( $subcategory_in_clause )
              OR category3 IN ( $subcategory_in_clause )");

Не могли бы вы попробовать этот вариант, не уверен, что он работает, но стоит попробовать

0 голосов
/ 05 марта 2014

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

$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 строки, второе - только в одну. Я не поверил, но ОТЛИЧИЕ!

0 голосов
/ 26 июня 2009

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

...