Сложное предложение WHERE с базой данных Zend с использованием нескольких операторов И ИЛИ


Я хочу сгенерировать это сложное предложение 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);

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

Ура!

Author: Tom Jowitt, 2010-12-08

4 answers

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

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

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

 22
Author: karim79, 2017-11-02 15:40:33

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

 2
Author: Alasdair Shields, 2016-08-31 09:00:02

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

$select->from('product');
$select->where('status = ?', $status);
$select->where('(attribute = ?', $a1);
$select->orWhere('attribute = ?)', $a2);
 0
Author: Vulman, 2014-05-16 13:29:44

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

$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
Author: FlameStorm, 2017-07-12 13:18:19