Запрос с несколькими терминами ИЛИ в WHERE возвращает всю таблицу - PullRequest
0 голосов
/ 24 апреля 2019

Может кто-нибудь сказать мне, почему эта команда SQL не работает?У меня есть форма с несколькими входами, т. Е. (Id) => номер счета, затем имя, фамилия и адрес электронной почты.Я хочу разрешить пользователю выполнять поиск в любом случае.

, если я оставлю код таким, какой он есть "с AND" .. при поиске только по (id) он просто отобразит строку идентификаторано он не будет отображать остальные результаты поиска, если я попытаюсь ввести первый, последний или адрес электронной почты, но если я изменю его на «ИЛИ», тогда все остальные поля ввода будут работать, отображая единственный результат, но если я введу простоидентификатор "номер счета" я буду отображать каждого клиента в моей таблице .. почему?что мне не хватает, чтобы мой код мог искать все входы?Спасибо

$firstname = $_POST['firstname'];
$lastname = $_POST['lastname'];
$email = $_POST['email'];
$firstname = "%$firstname%";
$lastname = "%$lastname%";
$email = "%$email%";    
$id = $_POST['id']; 



    $stmt = $conn->prepare("
    SELECT * FROM `Demo_Guests`
    WHERE  
    firstname LIKE :firstname 
    AND lastname LIKE :lastname
    AND email LIKE :email AND id = :id

    ");
    $stmt->bindValue(':id', $id, PDO::PARAM_INT);
    $stmt->bindValue(':firstname', $firstname,PDO::PARAM_STR);
    $stmt->bindValue(':lastname', $lastname,PDO::PARAM_STR);
    $stmt->bindValue(':email', $email,PDO::PARAM_STR);
    $stmt->execute();
    $result = $stmt->fetchAll(PDO::FETCH_OBJ);

foreach($result as $row){
            echo "<tr><td> 
            <a href=\"main_table.php?id={$row->id}\"> " . $row->id . "</a><br></td>";
            echo "<td>" . $row->firstname . "</td>";
            echo "<td>" . $row->lastname . "</td>";
            echo "<td>" . $row->email . "</td>";
            echo "<td>" . $row->reg_date . "</td></tr>";


}

1 Ответ

2 голосов
/ 24 апреля 2019

Чтобы расширить мой комментарий выше, который был:

Когда вы используете оператор 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%'.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...