Чтобы расширить мой комментарий выше, который был:
Когда вы используете оператор OR, вы должны быть уверены, что у вас нет firstname LIKE '%%'
, потому что это будет соответствовать всем.Вам нужно будет построить свой запрос, чтобы использовать только непустые значения, предоставленные в форме.
Это означает, что вам нужно будет построить свой запрос из НЕ пустых входных данных из формы поиска и пропуститьтермины, которые будут соответствовать всему в вашей таблице.
Возможно, было бы неплохо начать с просмотра данных поста и извлечения непустых значений, чтобы поместить в массив:
$searchFields = [];
foreach (['id', 'firstname', 'lastname', 'email'] as $searchField) {
if (!empty($_POST[$searchField])) {
$searchFields[$searchField] = $_POST[$searchField];
}
}
Это дает вам список всех полей, которые пользователь фактически заполнил. Этот список понадобится вам дважды - один раз для построения запроса и один раз для привязки.
if (count($searchFields) > 0) {
$queryStr = "SELECT * FROM `Demo_Guests` WHERE 0";
foreach (array_keys($searchFields) as $fieldName) {
$queryStr .= " OR " . $fieldName . " LIKE :" . $fieldName;
}
// ... the rest of the code goes here
} else {
return "you gotta give me something to work with!";
}
Два примечания: 1Я не делал id специальным случаем, и вам нужно будет сделать это в своем коде.2) WHERE 0
- это ярлык для ленивого человека, и вам не нужно будет потом делать дополнительную логику, чтобы решить, нужно ли вам добавить OR
к первому члену.Он превращается в WHERE 0 OR firstname LIKE '%Alice%'
, что функционально совпадает с WHERE firstname LIKE '%Alice%'
.
После того, как вы построите строку запроса, вы можете подготовить ее так, как вы делали выше, а затем выполнить привязки с тем же массивом, который вы использовалидля построения запроса.
$stmt = $conn->prepare($queryStr);
foreach($searchFields as $fieldName => $fieldValue) {
$stmt->bindValue(':'.$fieldName, "%$fieldValue%", PDO::PARAM_STR);
}
$stmt->execute();
Как и выше, я не создавал код для обработки поля id по-разному, но вы должны быть в состоянии справиться с этим.Если у вас было много полей разных типов, вы можете изменить структуру $ searchFields для включения информации о типах.Если id
является единственным исключением, вероятно, проще всего просто использовать оператор if в каждом цикле.
Added:
Этот поиск вернет все записи из базы данных, которые соответствуют ЛЮБОМУ извходные критерии.Так что, если пользователь ищет firstName LIKE '%Ali%' OR lastName LIKE '%Smi%'
, вы можете вернуть Алису Смит, Алисию Смит, Фреда Смита и Алису Джонс.
Если, однако, вы хотите, чтобы этот поиск возвращал только Алису Смит и Алисию Смит, а нечем использовать OR
, вы используете AND
.Поиск будет давать меньше результатов, поэтому он будет немного менее щадящим для неверно введенных имен и т. Д.
Единственное другое изменение в коде - это то, что ярлык ленивого человека также должен измениться:
if (count($searchFields) > 0) {
$queryStr = "SELECT * FROM `Demo_Guests` WHERE 1";
foreach (array_keys($searchFields) as $fieldName) {
$queryStr .= " AND " . $fieldName . " LIKE :" . $fieldName;
}
// ... the rest of the code goes here
} else {
return "you gotta give me something to work with!";
}
WHERE 1 AND first_name LIKE '%Ali%'
функционально аналогичен WHERE first_name LIKE '%Ali%'
.
Обратите внимание, что в этом случае, если пользователь указывает идентификатор, вы захотите полностью игнорировать другие поля поиска.В противном случае, если они укажут идентификатор и имя, которые не совпадают, они вообще не получат никаких результатов.