Сложные предложения WHERE с использованием PHP Doctrine ORM

StackOverflow https://stackoverflow.com/questions/1049617

  •  20-08-2019
  •  | 
  •  

Вопрос

Для построения запросов я использую ORM PHP Doctrine.Однако я не совсем понимаю, как написать следующее предложение WHERE, используя DQL (язык запросов Doctrine):

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

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

Кроме того, есть ли разница между методами «где», «andWhere» и «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)");
Это было полезно?

Решение

По моему опыту, каждый комплекс 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 – условные запросы построителя запросов...Если заявления? как отметил @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");

Обратите внимание на «AND TRUE», трюк, позволяющий синтаксическому анализатору не игнорировать внешние круглые скобки.

andWhere можно резюмировать как:
Ранее добавленные условия с учетом оператора 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);
}

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

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

Что касается разницы междуwhere, andwhere и addwhere, я не думаю, что существует значительная разница с тем, когда я в последний раз читал источник.Однако я бы посоветовал вам прочитать источник Doctrine.Это действительно просто и помогает заполнить пробелы в документации (их много).Что касается сложных операторов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 строки, второе – только в одну.Я не поверил, но РАЗНИЦА ЕСТЬ!

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

не были бы вы так любезны попробовать этот вариант, не уверен, что он сработает, но попробовать стоит

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top