Сложное предложение 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.
Ура!
4 answers
Это был бы "официальный" способ указать вам скобки, как указано (см. Пример № 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);
Если ваш атрибут является одним и тем же столбцом таблицы, и вы хотите проверить, равен ли он одному из нескольких значений, чем вы можете использовать В:
$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"