41

我正在使用 PHP Doctrine ORM 来构建我的查询。但是,我似乎不太明白如何使用 DQL(Doctrine Query Language)编写以下 WHERE 子句:

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”、“andWhere”和“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)");
4

7 回答 7

73

根据我的经验,每个复杂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
于 2010-01-11T02:18:32.427 回答
25

正确的方法可以在学说 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);
于 2016-08-18T17:12:18.703 回答
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");

请注意“AND TRUE”,这是一个 hack,以便解析器不会忽略外括号。

于 2009-06-26T16:45:29.767 回答
1

andWhere 可以概括为:
先前添加的 Condition(s) Aware WHERE 语句

您可以安全地使用andWhere代替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部分,如果之前添加了另一个 where 语句
  3. 附加条件
于 2011-02-05T09:37:13.237 回答
0

至于 where 和 where 和 addwhere 之间的区别,我认为与我上次阅读源代码时没有显着差异。但是,我鼓励您阅读 Doctrine 源代码。这真的很简单,并且有助于填补文档中的漏洞(有很多)。至于复杂的 where 语句,我自己也想知道,但还没有需要。

于 2009-06-26T15:09:21.420 回答
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 行上,第二个语句只写在一行上。我不相信,但有区别!

于 2014-03-05T09:58:01.473 回答
0
$q->andWhere("category1 IN ( $subcategory_in_clause )
              OR category2 IN ( $subcategory_in_clause )
              OR category3 IN ( $subcategory_in_clause )");

你会这么好心尝试这个变种,不确定它是否有效,但值得一试

于 2019-05-15T21:52:23.947 回答