具有使用多个 AND OR 运算符Zend_Db的复杂 WHERE 子句

2022-08-31 00:49:23

我想在Zend_Db生成这个复杂的 WHERE 子句:

SELECT * 
FROM 'products' 
WHERE 
    status = 'active' 
    AND 
    (
        attribute = 'one' 
        OR 
        attribute = 'two' 
        OR 
        [...]
    )
;

我试过这个:

$select->from('product');
$select->where('status = ?', $status);
$select->where('attribute = ?', $a1);
$select->orWhere('attribute = ?', $a2);

并产生了:

SELECT `product`.* 
FROM `product` 
WHERE 
    (status = 'active') 
    AND 
    (attribute = 'one') 
    OR 
    (attribute = 'two')
;

我确实找到了一种使这项工作的方法,但我觉得使用PHP首先组合“OR”子句,然后使用Zend_Db where()子句将它们组合在一起,这是一种“作弊”。PHP 代码:

$WHERE = array();
foreach($attributes as $a):
    #WHERE[] = "attribute = '" . $a . "'";
endforeach;
$WHERE = implode(' OR ', $WHERE);

$select->from('product');
$select->where('status = ?', $status);
$select->where($WHERE);

这产生了我一直在寻找的东西。但是我很好奇,是否有一种“官方”方式可以使用Zend_Db工具来获得复杂的 WHERE 语句(这真的不太复杂,只是添加一些括号),而不是先在 PHP 中组合它。

干杯!


答案 1

这将是获得指定括号的“官方”方式(请参阅Zend_Db_Select文档中的示例#20):

$a1 = 'one';
$a2 = 'two';
$select->from('product');
$select->where('status = ?', $status);
$select->where("attribute = $a1 OR attribute = $a2");

因此,您正在做的事情似乎是合理的,因为您事先不知道自己有多少属性。


答案 2

如果使用所选的答案,则需要记住在构造查询之前引用值以防止SQL注入。

另一个使用Zend Db Select创建查询并引用值的选项是分2个阶段完成:

/// we just use this select to create the "or wheres"
$select1->from('product');
foreach($attributes as $key => $a) {
    if ($key == 0) {
    /// we don't want "OR" for first one
        $select1->where("attribute = ?", $a);
    } else {
        $select1->orWhere("attribute = ?", $a);
    }   
}

/// now we construct main query
$select2->from('product');
$select2->where('status = ?', $status);
$select2->where(implode(' ', $select1->getPart('where')));

通过这种方式,Zend Db Select可以完成所有SQL生成。一个古老的问题,但希望这个想法可能对有类似问题的人有用。


推荐