Я хочу создать это сложное предложение 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.
Ура!
Это был бы «официальный» способ получить скобки в соответствии с указанными (см. Пример № 20 в документации Zend_Db_Select
):
$a1 = 'one'; $a2 = 'two'; $select->from('product'); $select->where('status = ?', $status); $select->where("attribute = $a1 OR attribute = $a2");
Итак, то, что вы делаете, кажется разумным, учитывая, что вы не знаете, сколько атрибутов у вас есть раньше времени.
Если вы используете выбранный ответ, вам нужно будет запомнить значения перед построением запроса для защиты от 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. Старый вопрос, но, надеюсь, эта идея может пригодиться кому-то с аналогичной проблемой.
Я использую это решение и, похоже, работает как нужно.
$select->from('product'); $select->where('status = ?', $status); $select->where('(attribute = ?', $a1); $select->orWhere('attribute = ?)', $a2);
Если ваш атрибут является одним и тем же столбцом таблицы, и вы хотите проверить его на одно из нескольких значений, вы можете использовать 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"