Сложное предложение WHERE с Zend_Db с использованием нескольких операторов AND OR - PullRequest
15 голосов
/ 08 декабря 2010

Я хочу создать это сложное предложение WHERE в Zend_Db:

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, чтобы сначала объединить предложения «ИЛИ», а затем объединить их с помощью предложения 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);

Это произвело то, что я искал. Но мне любопытно, есть ли «официальный» способ получения этого сложного оператора WHERE (который на самом деле не так уж и сложен, просто добавив несколько скобок) с использованием инструмента Zend_Db вместо его сначала объединения в PHP.

Ура!

Ответы [ 4 ]

22 голосов
/ 08 декабря 2010

Это был бы «официальный» способ получить скобки, как указано (см. Пример № 20 в документации Zend_Db_Select):

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

Итак, что вывыполнение кажется разумным, учитывая, что вы заранее не знаете, сколько у вас атрибутов.

3 голосов
/ 31 августа 2016

Если вы используете выбранный ответ, вам нужно не забывать заключать в кавычки значения, прежде чем создавать запрос для защиты от внедрения 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. Старый вопрос, но, надеюсь, эта идея может пригодиться кому-то с похожей проблемой.

0 голосов
/ 12 июля 2017

Если ваш атрибут - это тот же столбец таблицы, и вы хотите проверить его на наличие одного из нескольких значений, то вы можете использовать IN:

$select->from('product');
$select->where('status = ?', $status);
$select->where('attribute IN (?)', [$a1, $a2, ...]);

или

$select->where('attribute IN (:someName)');
$select->setParameter('someName', [$a1, $a2, ...]);

В противном случае я не вижу альтернативы вышеупомянутому решению с "attribute = $a1 OR attribute = $a2"

0 голосов
/ 16 мая 2014

Я использую это решение, и оно работает как хотелось.

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