使用PHP规则ORM的复杂WHERE子句
我正在使用PHP原则ORM构建我的查询。然而,我似乎不太明白如何使用DQL(条令查询语言)编写以下WHERE子句: 如何指定括号的位置 目前我的PHP代码中包含以下内容:使用PHP规则ORM的复杂WHERE子句,php,mysql,doctrine,dql,Php,Mysql,Doctrine,Dql,我正在使用PHP原则ORM构建我的查询。然而,我似乎不太明白如何使用DQL(条令查询语言)编写以下WHERE子句: 如何指定括号的位置 目前我的PHP代码中包含以下内容: ->where('name = ?', 'ABC') ->andWhere('category1 = ?', 'X') ->orWhere('category2 = ?', 'X') ->orWhere('category3 = ?', 'X') ->andWhere('price > ?'
->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”方法之间是否有区别
更新
好的,似乎无法使用DQL进行复杂的查询,所以我一直在尝试手动编写SQL,并使用andWhere()方法添加它。然而,我使用WHERE..IN和document似乎去掉了我的括号:
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause)");
至于where、andwhere和addwhere之间的区别,我认为与上次阅读源代码时没有明显区别。然而,我鼓励你阅读教义来源。它非常简单,有助于填补文档中的漏洞(有很多)。至于复杂的where语句,我自己也很想知道,但还没有必要使用它。由于似乎无法使用DQL进行复杂的查询,我编写了以下SQL以传递给andWhere()方法:
请注意“AND TRUE”,这是一种黑客攻击,这样解析器就不会忽略外括号。根据我的经验,每个复杂的
,其中
函数都分组在括号内(我使用的是原则1.2.1)
$q->where('name=?','ABC')
->其中('category1=?或category2=?或category3=?',数组('X','X','X'))
->andWhere('价格<?',10)
生成以下SQL:
WHERE name = 'ABC'
AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X')
AND price < 10
其中name='ABC'
和(类别1='X'或类别2='X'或类别3='X')
价格<10
其中可以概括为:先前添加的条件感知WHERE语句 您可以安全地使用和where代替where。(它引入了非常小的开销,这在下面的第2个列表项中进行了说明。) andWhere is的实施:(原则1.2.3) 可以理解为
根据我的经验,我有时会看到以下两者之间的区别:
$q->andWhere("(category1 IN $subcategory_in_clause
OR category2 IN $subcategory_in_clause
OR category3 IN $subcategory_in_clause)");
及
第一条语句写在3行上,第二条语句只写在一行上。我不相信,但这是不同的 正确的方法可以在@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);
请您尝试一下这个变体,不确定它是否有效,但值得一试我认为anushr的解决方案要好得多。没有黑客攻击和使用准备好的声明。另一个解决方案可以在这里找到正是我所寻找的!这正是我讨厌教义的原因。这是不可能阅读和理解的。你也可以这样做:$ors=$qb->expr()->orX()$ors->add($qb->expr()->like('firstName',$qb->expr()->literal(%john%”))$ors->add($qb->expr()->like('lastName',$qb->expr()->literal(“%john%”))$qb->andWhere($ors);或者,您可以跳过所有这些噪声,将一个DQL字符串连接在一起。。。请确保您没有向SQL注入敞开大门。
WHERE name = 'ABC'
AND (category1 = 'X' OR category2 = 'X' OR category3 = 'X')
AND price < 10
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);
}
$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)");
$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);
$q->andWhere("category1 IN ( $subcategory_in_clause )
OR category2 IN ( $subcategory_in_clause )
OR category3 IN ( $subcategory_in_clause )");