За последние 24 часа нас посетили 22323 программиста и 1049 роботов. Сейчас ищут 669 программистов ...

Подготовленные запросы для поиска на сайте

Тема в разделе "PHP для новичков", создана пользователем iiwanc, 5 июл 2022.

  1. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Здравствуйте!
    Простите, если не сюда пишу.

    Только изучаю php в универе. Код может быть скорее всего оптимизирован, но мне бы сперва работоспособности добиться.
    Пытаюсь сделать подготовленные запросы.
    PHP:
    1. <?php
    2. mysqli_report(MYSQLI_REPORT_ALL);
    3. try {
    4. require_once 'connfig.php';
    5. mysqli_set_charset($db, "utf8");
    6. /*$query=$_GET['query'];
    7. $array = [
    8.     '?' => '$query'
    9. ];*/
    10. /*$sql = "SELECT * FROM tovar WHERE content = ?";*/
    11. $query = $_POST['query'];
    12.  
    13. $array = array(
    14.     '?' => $query,
    15.     '?' => 'info'
    16.     );
    17. /* Создаём подготовленное утверждение */
    18. $stmt = mysqli_stmt_init($db);
    19. $sql = mysqli_stmt_prepare($stmt, "SELECT * FROM tovar WHERE content = ?");
    20.  
    21. /* Связываем переменные с метками */
    22. mysqli_stmt_bind_param($stmt, "s", $sql);
    23.  
    24. /* Выполняем запрос */
    25.  
    26. /* Связываем переменные результата */
    27.  
    28. /* Получаем значение */
    29.  
    30. printf(" находится в районе %s\n", $query);
    31.  
    32. }
    33. catch (Exception $e) {
    34.   echo $e->getMessage();
    35. }
    36. ?>
    Пишу простой поиск по базе. Пользователь забивает уникальный ID из 12 знаков и получает информацию из столбцов info, content и date_created.
    Подскажите, пожалуйста, как это реализовать?
    А то у меня сейчас выводится только тот код, что пользователь забил в поисковую форму.
    Очень хочу разобраться.

    Буду благодарен советам.
     
  2. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.551
    Симпатии:
    1.754
    Прочитайте внимательно, у вас бред нарисован сивой кобылы. https://www.php.net/mysqli_stmt_execute. Там есть такой пример, как у вас.
     
    miketomlin нравится это.
  3. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Да, читаю эту страницу.
    А какой пример подойдет?
     
  4. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Переписал:
    PHP:
    1. mysqli_report(MYSQLI_REPORT_ALL);
    2. try {
    3. require_once 'connfig.php';
    4. mysqli_set_charset($db, "utf8");
    5.  
    6.  
    7. /* Подготавливаем утверждение на вставку строк */
    8. $stmt = mysqli_prepare($db, 'SELECT * FROM tovar WHERE content = ?');
    9.  
    10. mysqli_stmt_bind_param($stmt, "s", $tovar);
    11.  
    12. /* Выполняем утверждение */
    13. mysqli_stmt_execute($stmt, ['info', 'content', 'date_created']);
    14.  
    15. /* Получаем все строки из myCity */
    16. while ($row = mysqli_fetch_assoc($result)) {
    17.     printf("%s (%s)\n", $row["info"], $row["content"], $row["date_created"]);
    18. }
    19.  
    20. }
    21. catch (Exception $e) {
    22.   echo $e->getMessage();
    23. }
    Подскажите, пожалуйста, где ошибся
     
  5. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    простите, не обновил страницу. не увидел mysqli_stmt::get_result
     
  6. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.790
    Симпатии:
    649
    1) mysqli:: prepare
    2) mysqli_stmt::bind_param
    3) mysqli_stmt::execute
    4) mysqli_stmt::get_result
    5) mysqli_result::fetch_assoc в цикле

    stmt_init, mysqli_stmt:: prepare, mysqli_stmt::fetch используются значительно реже.
    --- Добавлено ---
    P.S. После get_result уже можно закрывать подготовленный запрос. Вся выборка хранится в объекте result.
    --- Добавлено ---
    P.P.S. Для поиска «уникального ID» можно просто профильтровать и/или проэкранировать введенное значение с последующим обычным query ;)
    --- Добавлено ---
    В MySQLi исключения используются для отладки. Для обычных целей вы сами должны генерировать исключения (на основе возвращаемых методами значений).
     
  7. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    PHP:
    1. mysqli_report(MYSQLI_REPORT_ALL);
    2. try {
    3. require_once 'connfig.php';
    4. mysqli_set_charset($db, "utf8");
    5.  
    6. $stmt = mysqli_prepare($db, 'SELECT * FROM tovar WHERE content = ?');
    7.  
    8. mysqli_stmt_bind_param($stmt, "s", $tovar);
    9.  
    10. mysqli_stmt_execute($stmt, ['info', 'content', 'date_created']);
    11. $result = mysqli_stmt_get_result($stmt);
    12.  
    13. while ($row = mysqli_fetch_assoc($result)) {
    14.     printf("%s (%s)\n", $row["info"], $row["content"], $row["date_created"]);
    15. }
    16.  
    17. }
    18. catch (Exception $e) {
    19.   echo $e->getMessage();
    20. }
    Поправьте, пожалуйста
     
  8. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.743
    Симпатии:
    1.319
    Адрес:
    Лень
    @iiwanc, версию PHP какую используешь ?
     
  9. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Текущая версия PHP: 5.6.402.0
     
  10. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.790
    Симпатии:
    649
    Да, параметр $array – это ультра новая фишка. У функции mysqli_stmt_execute первый обязательный параметр – вообще НЕ массив ;) Читайте нормально доки, включая примеры, как вам выше писали.
     
  11. mkramer

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

    С нами с:
    20 июн 2012
    Сообщения:
    8.551
    Симпатии:
    1.754
    Надо 3.0 использовать :))

    А если пытаться понять примеры, а не копировать их? Никак? Вообще всё вместе, и бинд, и передача массива.... И параметры, которые нафиг не нужны в запросе, тоже заодно...
    --- Добавлено ---
    И это при том, что дока на русском языке, если что
     
  12. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    все 5 пунктов в моем случае обязательно использовать?
     
  13. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.790
    Симпатии:
    649
    Да, тяжко, когда бэкграунд никакой. Можно почитать статейку на сайте доков мускула, чтобы лучше понимать суть подготовленных выражений. execute принимает значения для «входного» параметра запроса (это то, что подставляется на место «?»). Причем не обязательно это значение передавать прямо в метод execute. Традиционный (и более общий, т.к. можно уточнить тип) для MySQLi способ – использовать bind_param.

    Да. Вместо bind_param можно использовать прямую передачу значения параметра в execute, о чем я выше написал. Но этот способ не поддерживается в вашей версии пыха.
    --- Добавлено ---
    Обратите внимание, что в bind_param, начиная со второго параметра, передаются по сути не значения, а ссылки на переменные (значения можно записать и после вызова этого метода).
     
    iiwanc нравится это.
  14. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Спасибо за советы. Буду изучать.
    Правильно заметили, бэкграунд никакой у меня. Фронтендом 5 лет занимался. В бэкграунд вообще никак не лез
     
  15. MouseZver

    MouseZver Суперстар

    С нами с:
    1 апр 2013
    Сообщения:
    7.743
    Симпатии:
    1.319
    Адрес:
    Лень
    Можешь перейти на PDO как самый близкий вариант.

    Это актуальная версия для программирования ? Что по этому поводу Преподаватель говорил ?
    --- Добавлено ---
    Документацию читал ? в PHP самая идеальная документация. Откуда переменной $result взяться в 16 строке ?
     
  16. ADSoft

    ADSoft Старожил

    С нами с:
    12 мар 2007
    Сообщения:
    3.820
    Симпатии:
    736
    Адрес:
    Татарстан
    бэкграунд - это фон... имеется ввиду общие знания.... вы же путаете с бэкендом... серверной частью))))
    либо не понимаете даже этого ))))
     
  17. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    PHP:
    1. <?php
    2. include 'connfig.php';
    3. mysqli_set_charset($db, "utf8");
    4. $zapros=$_POST['query'];
    5. $query = "SELECT * FROM tovar WHERE content = ?";
    6.  
    7. $stmt = mysqli_prepare($db, $query);
    8. mysqli_stmt_bind_param($stmt, "s", $zapros);
    9.  
    10. $result = mysqli_stmt_get_result($stmt);
    11.  
    12. if (mb_strlen($zapros) < 12) {
    13.     echo '<p>Слишком короткий поисковый запрос.</p>';
    14. } else if (mb_strlen($zapros) > 12) {
    15.     echo '<p>Слишком длинный поисковый запрос.</p>';
    16. }
    17.  
    18. while ($row = mysqli_fetch_assoc($result)) {
    19.     foreach ($row as $r) {
    20.         $str=$r['info'];
    21.         $stra=$r['content'];
    22.         $strm=$r['date_created'];
    23.             echo "<p>Ваш ID: " . htmlentities($stra, ENT_QUOTES, 'UTF-8') . "</p>";
    24.             echo "<p>Изделие: " . htmlentities($str, ENT_QUOTES, 'UTF-8') . "</p>";
    25.             echo "<p>Дата производства: " . htmlentities($strm, ENT_QUOTES, 'UTF-8') . "</p>";
    26.         }
    27.     }
    28. ?>
    Но выводимый результат дублируется. Имеется вид:
    Ваш ID:
    Изделие:
    Дата производства:
    Ваш ID: f
    Изделие: f
    Дата производства: f
    Ваш ID: 2
    Изделие: 2
    Дата производства: 2
    Ваш ID: h
    Изделие: h
    Дата производства: h


    Подскажите, пожалуйста, в чем проблема.
    Буду благодарен советам.
     
  18. Androbim

    Androbim Новичок

    С нами с:
    17 июн 2021
    Сообщения:
    49
    Симпатии:
    9
    А если перед циклом:
    Код (Text):
    1. var_dump($row);
    ?
     
  19. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    @Androbim, спасибо.
    Натолкнули на мысль.
    Избавился от foreach. Теперь корректно отображается
     
  20. Androbim

    Androbim Новичок

    С нами с:
    17 июн 2021
    Сообщения:
    49
    Симпатии:
    9
    Запомните этот момент, вардамп - наше все :)
     
    iiwanc нравится это.
  21. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Продолжаю совершенствовать код. Включаю протоколирование и перехват ошибок:
    PHP:
    1. <?php
    2. mysqli_report(MYSQLI_REPORT_ALL);
    3. try {
    4. include './svaz/conn.php';
    5. mysqli_set_charset($db, "utf8");
    6. $zapros=$_POST['query'];
    7. $query = "SELECT * FROM tovar WHERE content = ?";
    8.  
    9. $stmt = mysqli_prepare($db, $query);
    10. mysqli_stmt_bind_param($stmt, "s", $zapros);
    11.  
    12. $result = mysqli_stmt_get_result($stmt);
    13.  
    14. if (mb_strlen($zapros) < 12) {
    15.     echo '<p>Слишком короткий поисковый запрос.</p>';
    16. } else if (mb_strlen($zapros) > 12) {
    17.     echo '<p>Слишком длинный поисковый запрос.</p>';
    18. }
    19.  
    20. while ($row = mysqli_fetch_assoc($result)) {
    21.         $str=$row['info'];
    22.         $stra=$row['content'];
    23.         $strm=$row['date_created'];
    24.             echo "<p>Ваш ID: " . htmlentities($stra, ENT_QUOTES, 'UTF-8') . "</p>";
    25.             echo "<p>Изделие: " . htmlentities($str, ENT_QUOTES, 'UTF-8') . "</p>";
    26.             echo "<p>Дата производства: " . htmlentities($strm, ENT_QUOTES, 'UTF-8') . "</p>";
    27.     }
    28. }
    29. catch (Exception $e) {
    30.   echo $e->getMessage();
    31. }
    32. ?>
    В результате появляется сообщение: No index used in query/prepared statement SELECT * FROM tovar WHERE content = ?
    Если отключить протоколирование, то все работает.
    Объясните, пожалуйста, что делаю не так. Или это норма?
    Буду благодарен советам.
     
  22. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.790
    Симпатии:
    649
    У content надо поменять тип на varchar и создать для него индекс. Уникальный индекс, т.к. у вас в поле «уникальные ID».

    Название тупое у поля. Назовите артикулом и т.п. Если нет требования, чтобы поле с таким именем обязательно было.
     
  23. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    это вы про 24 строку говорите?
     
  24. miketomlin

    miketomlin Старожил

    С нами с:
    9 авг 2016
    Сообщения:
    3.790
    Симпатии:
    649
    Это я про бэкграунд ;)
    --- Добавлено ---
    Учите основы построения БД.
    --- Добавлено ---
    Mля, ничего не смущает?
    PHP:
    1. $result = mysqli_stmt_get_result($stmt);
    Вывод обычных ошибок (самого пыха) тоже включите.
     
  25. iiwanc

    iiwanc Новичок

    С нами с:
    20 май 2022
    Сообщения:
    16
    Симпатии:
    0
    Разобрался с таблицей с помощью mysql alter table add index.
    Но почему-то не ищет:
    PHP:
    1. <?php
    2. mysqli_report(MYSQLI_REPORT_ALL);
    3. try {
    4. include 'connfig.php';
    5. mysqli_set_charset($db, "utf8");
    6. $zapros=$_POST['query'];
    7. $query = "SELECT * FROM tovar WHERE content = ?";
    8.  
    9. $stmt = mysqli_prepare($db, $query);
    10. mysqli_stmt_bind_param($stmt, "s", $zapros);
    11. $result = mysqli_stmt_get_result($stmt);
    12.  
    13. if (!empty($query) && trim($query) !=''){
    14. if (mb_strlen($zapros) < 12) {
    15.     echo '<p>Слишком короткий поисковый запрос.</p>';
    16. } else if (mb_strlen($zapros) > 12) {
    17.     echo '<p>Слишком длинный поисковый запрос.</p>';
    18. }
    19.  
    20. while ($row = mysqli_fetch_assoc($result)) {
    21.         $str=$row['info'];
    22.         $stra=$row['content'];
    23.         $strm=$row['date_created'];
    24.             echo "<p>Ваш ID: " . htmlentities($stra, ENT_QUOTES, 'UTF-8') . "</p>";
    25.             echo "<p>Изделие: " . htmlentities($str, ENT_QUOTES, 'UTF-8') . "</p>";
    26.             echo "<p>Дата производства: " . htmlentities($strm, ENT_QUOTES, 'UTF-8') . "</p>";
    27.     }
    28. }
    29. }
    30. catch (mysqli_sql_exception $e) {
    31. $fd = fopen("./log/log.txt", 'w') or die("не удалось создать файл");
    32. $logir = $e->__toString();
    33. fwrite($fd, $logir);
    34. fclose($fd);
    35. }
    36. ?>
    Постоянно выводит, что Слишком короткий поисковый запрос.
    --- Добавлено ---
    Подскажите, пожалуйста
    --- Добавлено ---

    [​IMG]
    --- Добавлено ---
    [​IMG]