Игнорировать особые критерии WHERE

Я хочу выполнить параметризованный запрос для выполнения поиска по пользовательским параметрам. Есть довольно много параметров, и не все из них будут поставляться все время. Как я могу сделать стандартный запрос, который задает все возможные параметры, но игнорировать некоторые из этих параметров, если пользователь не выбрал значащее значение параметра?

Вот мнимый пример, иллюстрирующий то, что я собираюсь

$sql = 'SELECT * FROM people WHERE first_name = :first_name AND last_name = :last_name AND age = :age AND sex = :sex'; $query = $db->prepare($sql); $query->execute(array(':first_name' => 'John', ':age' => '27'); 

Очевидно, что это не сработает, потому что количество предоставленных параметров не соответствует числу ожидаемых параметров. Должен ли я обрабатывать запрос каждый раз, когда только указанные параметры включены в предложение WHERE, или есть способ заставить некоторые из этих параметров игнорировать или всегда возвращать true при проверке?

 SELECT * FROM people WHERE (first_name = :first_name or :first_name is null) AND (last_name = :last_name or :last_name is null) AND (age = :age or :age is null) AND (sex = :sex or :sex is null) 

При прохождении параметров поставьте null для тех, которые вам не нужны.

Обратите внимание: чтобы иметь возможность запускать запрос таким образом, emulation mode для PDO должен быть ON

Сначала начните, просто изменив строку $sql :

 $sql = 'SELECT * FROM people WHERE 1 = 1'; 

WHERE 1 = 1 позволит вам не включать дополнительные параметры …

Затем выборочно объединяйте строку $sql любым дополнительным параметром, имеющим значимое значение:

 $sql .= ' AND first_name = :first_name' $sql .= ' AND age = :age' 

Ваша строка $sql теперь содержит только параметры, которые вы планируете предоставлять, поэтому вы можете действовать по-прежнему:

 $query = $db->prepare($sql); $query->execute(array(':first_name' => 'John', ':age' => '27'); 

Если вы не можете решить свою проблему, изменив свой запрос … Есть несколько библиотек, которые помогают с сборкой запросов. Я использовал Zend_Db_Select в прошлом, но каждая структура, вероятно, имеет нечто похожее:

 $select = new Zend_Db_Select; $select->from('people'); if (!empty($lastName)) { $select->where('lastname = ?', $lastname); } $select->order('lastname desc')->limit(10); echo $select; // SELECT * FROM people WHERE lastname = '...' ORDER BY lastname desc LIMIT 10 

Я протестировал решение, данное @juergen, но оно дает PDOException, поскольку число связанных переменных не совпадает. Следующий (не очень элегантный) код работает независимо от каких-либо параметров:

 function searchPeople( $inputArr ) { $allowed = array(':first_name'=>'first_name', ':last_name'=>'last_name', ':age'=>'age', ':sex'=>'sex'); $sql = 'SELECT * FROM sf_guard_user WHERE 1 = 1'; foreach($allowed AS $key => $val) { if( array_key_exists( $key, $inputArr ) ){ $sql .= ' AND '. $val .' = '. $key; } } $query = $db->prepare( $sql ); $query->execute( $inputArr ); return $query->fetchAll(); } 

Применение:

 $result = searchPeople(array(':first_name' => 'John', ':age' => '27'));