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