Как бороться с проблемами mysqli? mysqli_fetch_array(): аргумент # 1 должен иметь тип mysqli_result

#php #sql #database #innodb

#php #mysqli #сообщение об ошибке

Вопрос:

В моей локальной среде / среде разработки запрос MySQLi выполняется нормально. Однако, когда я загружаю его в свою среду веб-хостинга, я получаю эту ошибку:

Фатальная ошибка: вызов функции-члена bind_param() для не-объекта в …

Вот код:

 global $mysqli;
$stmt = $mysqli->prepare("SELECT id, description FROM tbl_page_answer_category WHERE cur_own_id = ?");
$stmt->bind_param('i', $cur_id);
$stmt->execute();
$stmt->bind_result($uid, $desc);
 

Чтобы проверить мой запрос, я попытался выполнить запрос через панель управления phpMyAdmin, и результат в порядке.

Комментарии:

1. Возможно, вашему пользователю MySQL не хватает привилегий для выполнения SELECT запроса. Вы это проверили?

Ответ №1:

TL; DR

  1. Всегда имейте mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT); в своем коде подключения mysqli и всегда проверяйте ошибки PHP.
  2. Всегда заменяйте каждую переменную PHP в SQL-запросе вопросительным знаком и выполняйте запрос, используя подготовленный оператор. Это поможет избежать синтаксических ошибок всех видов.

Объяснение

Иногда ваш код MySQLi выдает ошибку, подобную mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given... Call to a member function bind_param()... или аналогичную. Или даже без каких-либо ошибок, но запрос все равно не работает. Это означает, что ваш запрос не удалось выполнить.

Каждый раз, когда запрос завершается неудачно, MySQL выдает сообщение об ошибке, объясняющее причину. В более старых версиях PHP такие ошибки не передавались в PHP, и все, что вы получите, это загадочное сообщение об ошибке, упомянутое выше. Следовательно, очень важно настроить PHP и MySQLi для сообщения вам об ошибках MySQL. И как только вы получите сообщение об ошибке, исправить его будет проще простого.

Как получить сообщение об ошибке в MySQLi

Прежде всего, всегда используйте эту строку перед подключением MySQLi во всех ваших средах:

 mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
 

После этого все ошибки MySQL будут перенесены в исключения PHP. Неперехваченное исключение, в свою очередь, приводит к фатальной ошибке PHP. Таким образом, в случае ошибки MySQL вы получите обычную ошибку PHP. Это мгновенно сообщит вам о причине ошибки. И трассировка стека приведет вас к точному месту, где произошла ошибка.

Как получить сообщение об ошибке от PHP

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

Поэтому вы должны установить для соответствующих параметров конфигурации следующие значения:

  • На сервере разработки
  • error_reporting должно быть установлено E_ALL значение;
  • log_errors должен быть установлен в 1 (удобно иметь журналы и на компьютере разработчика)
  • display_errors должно быть установлено значение 1
  • На рабочем сервере
  • error_reporting должно быть установлено E_ALL значение;
  • log_errors должно быть установлено значение 1
  • display_errors должен быть установлен в 0

После этого, когда запрос MySQL завершается неудачно, вы получите ошибку PHP, объясняющую причину. На реальном сервере, чтобы получить сообщение об ошибке, вам нужно будет проверить журнал ошибок.

Как на самом деле его использовать

Просто удалите любой код, который проверяет наличие ошибки вручную, все те or die() , if ($result) , try..catch и тому подобное. Просто напишите код взаимодействия с базой данных прямо сейчас:

 $stmt = $this->con->prepare("INSERT INTO table(name, quantity) VALUES (?,?)");
$stmt->bind_param("si", $name, $quantity);
$stmt->execute();
 

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

Что делать с полученным сообщением об ошибке

Прежде всего, вы должны найти проблемный запрос. Сообщение об ошибке содержит имя файла и номер строки точного места, где произошла ошибка. Для простого кода этого достаточно, но если ваш код использует функции или классы, вам может потребоваться выполнить трассировку стека, чтобы найти проблемный запрос.

После получения сообщения об ошибке вы должны прочитать и понять его. Это звучит слишком очевидно, если не снисходительно, но учащиеся часто упускают из виду тот факт, что сообщение об ошибке — это не просто сигнал тревоги, но на самом деле оно содержит подробное объяснение проблемы. И все, что вам нужно, это прочитать сообщение об ошибке и устранить проблему.

  • Скажем, если он говорит, что определенная таблица не существует, вы должны проверить орфографию, опечатки и регистр букв. Также вы должны убедиться, что ваш PHP-скрипт подключается к правильной базе данных
  • Или, если он говорит, что в синтаксисе SQL есть ошибка, тогда вам нужно проверить свой SQL. И проблемное место находится прямо перед частью запроса, указанной в сообщении об ошибке.

Если вы не понимаете сообщение об ошибке, попробуйте поискать его в Google. И при просмотре результатов придерживайтесь ответов, которые объясняют ошибку, а не прямо дают решение. Решение может не сработать в вашем конкретном случае, но объяснение поможет вам понять проблему и позволит вам решить проблему самостоятельно.

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

Список вещей, которые вы никогда не должны делать в отношении сообщений об ошибках

  • Никогда не используйте оператор подавления ошибок ( @ )! Это делает программиста неспособным прочитать сообщение об ошибке и, следовательно, не может исправить ошибку
  • Не используйте die() или echo или любую другую функцию для безоговорочной печати сообщения об ошибке на экране. PHP может сообщать об ошибках сам по себе и делать это правильно, зависит от среды — так что просто оставьте это для PHP.
  • Не добавляйте условие для проверки результата запроса вручную (например if($result) ). При включенных исключениях ошибок такое условие будет просто бесполезным.
  • Не используйте try..catch оператор для повторения сообщения об ошибке. Этот оператор следует использовать для выполнения некоторой обработки ошибок, например, отката транзакции. Но никогда не используйте его только для сообщения об ошибках — как мы узнали выше, PHP уже может это сделать, правильным способом.

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

У меня есть статья, которая может помочь в этом вопросе, как отлаживать взаимодействия с базой данных. Хотя он написан для PDO, принцип тот же. Просто следуйте этим инструкциям шаг за шагом, и либо ваша проблема будет решена, либо у вас возникнет ответственный вопрос о переполнении стека.

Комментарии:

1. @AdamWinter использование @ всегда неверно, и в данном конкретном случае в десять раз. Сообщения об ошибках для вашей программы — это то же самое, что боль для вашего тела. Он сообщает вам, что что-то не так, например, у вас сломана нога. И вы должны исправить ногу, а не просто принять обезболивающее и идти дальше. ТО ЖЕ САМОЕ ЗДЕСЬ. PHP сообщает вам, что нет ожидаемой переменной. Поэтому вам нужно исправить форму или что-то еще, чтобы сделать эту переменную доступной. Не просто написать код для обхода ошибки.

2. По большей части я согласен, однако с «вашим здравым смыслом» я не согласен, «Не просто писать код, чтобы обойти ошибку» как вы думаете, что делает try … catch, он обходит ошибку, чтобы предотвратить неконтролируемый выход кодовой базы, некоторые ошибки, которые вы не можете исправить внапример, сервер базы данных исчез, вам просто нужно обработать ошибку и обойти ошибку, чтобы получить допустимый результат.

3. @Barkermn01 это ваша забота, но вы делаете неправильные выводы из этого. Конечно, ваше приложение должно выдавать действительный результат (который в случае ошибки «Mysql исчез» должен быть общей страницей ошибок 500). Но вы должны понимать, что такой допустимый результат не относится к вашему коду базы данных. Ваш код, связанный с базой данных, должен работать с базой данных. В то время как отображение страницы с ошибкой должно быть проблемой другого кода. Смотрите здесь: phpdelusions.net/articles/error_reporting

4. я понимаю, что это было просто что-то вроде «Но никогда не используйте его только для сообщения об ошибках», это как бы исключает полностью объективные кодовые базы, например, мой MVC, если мои модели сталкиваются с ошибкой, им нужно обработать ошибку, а затем вернуть ее обратно, чтобы мой контроллер, в котором использование модели обернуто, мог справиться сошибка и представление ошибки, в данном случае, я использую это API, поэтому ошибка и вся информация о трассировке отправляются вызовом API, если он пришел из нашей удаленной системы (проверка происхождения), поскольку многие веб-материалы дозируют сейчас PHP-серверную часть REACT или Angular Front end

5. «Неперехваченное исключение, в свою очередь, приводит к фатальной ошибке PHP» Вызывает ли фатальную ошибку хорошая идея на РАБОЧЕМ сервере (для ошибок mysql)? Разве нет нескольких ситуаций, когда ошибка указывает на проблему, с которой должен справиться ваш скрипт, и продолжает, как может; например, сообщите пользователю, что вы не можете предоставить им эту информацию прямо сейчас, предупреждая оператора о расследовании? РЕДАКТИРОВАТЬ Я вижу, где нужно, вы пытаетесь .. поймать ошибки mysql (которые вы преобразовали в ошибки php).