За последние 24 часа нас посетили 14904 программиста и 1712 роботов. Сейчас ищут 1297 программистов ...

Поиск с помощью LIKE

Тема в разделе "PHP и базы данных", создана пользователем Булат Азат улы, 25 апр 2023.

  1. Булат Азат улы

    Булат Азат улы Активный пользователь

    С нами с:
    31 авг 2017
    Сообщения:
    61
    Симпатии:
    6
    Адрес:
    Республика Татарстан, город Казань
    Всех приветствую, товарищи!
    Хочу сделать поиск человека из БД по его данным, но почему-то данный запрос возвращает последнего из списка, независимо от введённых данных. А хотел бы, чтобы возвращал список из тех, данные которых совпали с запросом поиска. Не могли бы подсказать, в чём моя ошибка?
    PHP:
    1. $stmtKlientS = $mb->prepare("SELECT id, name, tel, email, FROM clients WHERE id = :id OR name LIKE :name OR tel LIKE :tel OR email LIKE :email ORDER BY name ");
    2. $stmtKlientS->bindValue(':id', (int)$_POST['klId']);
    3. $stmtKlientS->bindValue(':name', "%".trim($_POST['name'])."%");
    4. $stmtKlientS->bindValue(':tel', "%".(int)$_POST['tel']."%");
    5. $stmtKlientS->bindValue(':email', "%".trim($_POST['email'])."%");
    6. $stmtKlientS->execute();
    7.    
    8. $dataKlientS = $stmtKlientS->fetchAll(PDO::FETCH_ASSOC);
    9. foreach($dataKlientS as $itemKlientS){
    10.     $klientS = "<tr data-id='".$itemKlientS['id']."'><td>".$itemKlientS['id']."</td><td>".$itemKlientS['name']."</td><td>+7".$itemKlientS['tel']."</td><td>".$itemKlientS['email']."</td></tr>";
    11. }
    12. echo $klientS;
     
  2. Aleksandr.B

    Aleksandr.B Новичок

    С нами с:
    2 фев 2023
    Сообщения:
    158
    Симпатии:
    41
    Адрес:
    Барнаул
    $klientS .=
    PHP:
    1. <?php
    2. $stmtKlientS = $mb->prepare("SELECT id, name, tel, email, FROM clients WHERE id = :id OR name LIKE :name OR tel LIKE :tel OR email LIKE :email ORDER BY name ");
    3. $stmtKlientS->bindValue(':id', (int)$_POST['klId']);
    4. $stmtKlientS->bindValue(':name', "%".trim($_POST['name'])."%");
    5. $stmtKlientS->bindValue(':tel', "%".(int)$_POST['tel']."%");
    6. $stmtKlientS->bindValue(':email', "%".trim($_POST['email'])."%");
    7. $stmtKlientS->execute();
    8.  
    9. $dataKlientS = $stmtKlientS->fetchAll(PDO::FETCH_ASSOC);
    10. $klientS = '';
    11. foreach($dataKlientS as $itemKlientS){
    12. $klientS .= "<tr data-id='".$itemKlientS['id']."'><td>".$itemKlientS['id']."</td><td>".$itemKlientS['name']."</td><td>+7".$itemKlientS['tel']."</td><td>".$itemKlientS['email']."</td></tr>";
    13. }
    14. echo $klientS;
     
    Булат Азат улы нравится это.
  3. don.bidon

    don.bidon Активный пользователь

    С нами с:
    28 мар 2021
    Сообщения:
    915
    Симпатии:
    143
    @Булат, общие замечания:
    1) делать SELECT-ы без LIMIT-ов, а потом ещё и fetchAll() крайне вредно, вдруг результатом выборки будет лям записей, скрипт треснет по выделяемой оперативной памяти;
    2) даже без использования шаблонизаторов (php сам себе шаблонизатор) логику рекомендуется отделять от представления.
     
    Булат Азат улы нравится это.
  4. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.107
    Симпатии:
    1.243
    Адрес:
    там-сям
    Последнюю запись он возвращает потому что у тебя echo один раз выполняется. Если хочешь выводить каждую запись результата, помести echo внутрь цикла.
    --- Добавлено ---
    Ну или как @Aleksandr.B указал: .= будет подклеивать новые строки к результату, накапливать его перед выводом.
    --- Добавлено ---
    Но помоему проще было бы использовать мощь PHP как языка для веб: при выводе тебе можно обойтись без промежуточной переменной.

    PHP:
    1. $klientS = "<tr data-id='".$itemKlientS['id']."'><td>".$itemKlientS['id']."</td><td>".$itemKlientS['name']."</td><td>+7".$itemKlientS['tel']."</td><td>".$itemKlientS['email']."</td></tr>";
    2. echo $klientS;
    работает так же как
    PHP:
    1. ?>
    2.  
    3. <tr data-id="<?= $itemKlientS['id'] ?>">
    4.   <td><?= $itemKlientS['id'] ?></td>
    5.   <td><?= $itemKlientS['name'] ?></td>
    6.   <td>+7<?= $itemKlientS['tel'] ?></td>
    7.   <td><?= $itemKlientS['email'] ?></td>
    8. </tr>
    9.  
    10. <?php
    --- Добавлено ---
    Так ведь нагляднее, правда? Легче править когда понадобится.
     
    Булат Азат улы нравится это.
  5. Булат Азат улы

    Булат Азат улы Активный пользователь

    С нами с:
    31 авг 2017
    Сообщения:
    61
    Симпатии:
    6
    Адрес:
    Республика Татарстан, город Казань
    @Aleksandr.B, спасибо! Забыл точку поставить.
    @don.bidon, спасибо! Как-то не додумался ставить LIMIT-ы. Теперь поставил везде, где может выдать очень много результатов.
    @don.bidon, имеете ввиду, что нужно использовать апострофы?
    @artoodetoo, знаю, что так делают. Но я не совсем понимаю, как это делается.
    У меня есть очень длинные подобные строки с HTML-кодом с присваиванием к переменным. Действительно, очень неудобно править, поэтому я обычно правку делаю в отдельном HTML-файле, а потом копирую нужное в PHP, в строку.
    Например, при входе в админ-зону создаётся сессия, после проверка - если существует сессия, к какой-то переменной присваиваем текст с TML-кодом (который должен отображаться только тем, кто зашёл в админку). Можно ли данный код переделать в такой, который вы показали выше?
    PHP:
    1. <?php
    2. require_once("adminRt.php");
    3. require(__DIR__ . '/admin/' . $rtAdm[$routePath]);
    4.  
    5. $style = "<link href='/css/styleAdmin.css' type='text/css' rel='stylesheet'>";
    6. $JS = "<script src='/js/scriptAdmin.js' type='text/javascript'></script>";
    7.  
    8. if (isset($_POST['adminLogBtn'])){
    9.     $pwHash = password_hash("A6hTYqBQ9ug", PASSWORD_DEFAULT);
    10.     //$pwHash = "$2y$10$G175h4oBdNp3MlxSvH0Br./WASbhwR.m/RvmeV5on9TOpyrOWzJce";
    11.     $entLog = "Temp001";
    12.     if($_POST['entLog'] == $kerIsm && password_verify($_POST['passw'], $pwHash) == true){
    13.         $_SESSION['ADMIN'] = 1;
    14.         $topContent = $adminContent;
    15.     } else {
    16.         echo "<p style='text-align:center; margin:50px;'>Не верны логин или пароль. <br><a href='/admin/' target='_self'>Попробуйте ещё раз.</a></p>";
    17.     }
    18. } elseif (isset($_SESSION['ADMIN'])){
    19.     $topContent = $adminContent;
    20. } else {
    21.     $titleName = "";
    22.     $description = "";
    23.     $topContent = "<form action='/admin/' method='POST' name='adminEnt' id='adminEnt'><input required type='text' name='entLog' id='entLog' placeholder='Логин' maxlength='40'><input required type='password' name='passw' id='passw' placeholder='Пароль' maxlength='40'><input type='submit' value='Войти' name='adminLogBtn' id='adminLogBtn'></form>";
    24. }
    25. ?>
    А на второй странице к переменной $adminContent присваивается длинная строка с HTML-кодом. Можно ли эту строку переделать на нормальный?

    И, раз уж привёл данный код, хотел бы спросить насчёт паролей, хотя тема другая. Как сохранить КЭШ пароля, если он каждый раз меняется? Хотел присвоить к переменной $pwHash кэш - не получается. Работает, если только из "открытого" пароля на месте КЭШ сделать и там же его проверить с помощью password_verify().

    А по теме - не совсем смог решить проблему (то есть их там два оказалось). Теперь выводит весь список. Ошибку я понял, просто пока не могу придумать, как решить её более правильно.
    Есть список с именами людей, их телефонами, эл. почтами, датами их регистрации и т.п.... Есть форма поиска клиентов - там поля ввода для ID клиента (ключ БД), его имени, телефона, почты и т.д.. Я хотел сделать так, чтобы при вводе например, в поле ID цифры "6" и в поле телефон "1234" (оставив другие поля пустыми), и нажатии кнопки поиска, с помощью AJAX отправляется запрос, и возвращается список (в данном случае) клиента, у которого ID в базе - "6" и клиента, у которгого телефонный номер содержит цифры "1234".

    Но не продумал я то, что, как я понимаю, поля, которые не заполняются и остаются пустыми, проходят поиск с "LIKE" и подходят для всех клиентов в списке. Я могу фильтровать пустые данные в $_POST[''], принимаемым по AJAX, но как убрать их из запроса? Может, есть код MySQL, с помощью которого можно пропустить поиск, если в значении нет данных?
     
  6. Visman

    Visman Новичок

    С нами с:
    22 апр 2023
    Сообщения:
    12
    Симпатии:
    2
    Адрес:
    Сибирь
    Нужно в самом запросе конструировать условие на основе пришедших данных.
    PHP:
    1. $query = "SELECT id, name, tel, email, FROM clients WHERE ";
    2. $id = $_POST['klId'] ?? '';
    3. $x  = '';
    4. if ('' != $id) {
    5.     $query .= $x . 'id = :id ';
    6.     $x = 'OR '; // или AND ?
    7. }
    8. $name = trim($_POST['name'] ?? '');
    9. if ('' != $name) {
    10.     $query .= $x . 'name LIKE :name ';
    11.     $x = 'OR '; // или AND ?
    12. }
    13. .....
    14. $query .= 'ORDER BY name';
    15.  
    16. $stmtKlientS = $mb->prepare($query);
    17. if ('' != $id) {
    18.     $stmtKlientS->bindValue(':id', (int) $id);
    19. }
    20. if ('' != $name) {
    21.     $stmtKlientS->bindValue(':name', "%".$name."%");
    22. }
    23. ....
     
    Булат Азат улы нравится это.
  7. artoodetoo

    artoodetoo Суперстар
    Команда форума Модератор

    С нами с:
    11 июн 2010
    Сообщения:
    11.107
    Симпатии:
    1.243
    Адрес:
    там-сям
    Давай всё-таки предполагать что вычисления и вывод разделены. Даже если они в одном php файле, вывод лучше делать после добычи даных из базы и различных вычислений. Это путь к надежному и легко читаемому коду.

    Сообщения об ошибках без тегов html (!!!) копят в переменной-массиве, а в шаблоне выводят их в цикле, добавляя оформление - теги, стили и т.п.

    Ну и конечно шаблон может содержать условия типа "для админа выводим такую секцию". Это логика отображения, а не бизнес-логика. Так что в шаблоне это вполне уместно.
     
  8. Булат Азат улы

    Булат Азат улы Активный пользователь

    С нами с:
    31 авг 2017
    Сообщения:
    61
    Симпатии:
    6
    Адрес:
    Республика Татарстан, город Казань
    @Visman, спасибо большое! Всё работает!
    @artoodetoo, спасибо, но мне, похоже, придётся создать отдельную тему с этим вопросом - не могу я как-то нормально такой код сделать, с "открытым" HTML - знаний не хватает. Сделал бы, если бы в переменную можно было поместить условие. А это, как знаю, нельзя.
     
    artoodetoo нравится это.