Что делать с проблемами mysqli? Ошибки типа mysqli_fetch_array(): Аргумент № 1 должен иметь тип mysqli_result и тому подобное

#php #html #mysql #mysqli

#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:

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, которая объясняет причину. На действующем сервере, чтобы получить сообщение об ошибке, вам придется проверить журнал ошибок.

В случае вызова AJAX на сервере разработки откройте DevTools (F12), затем вкладку Сеть. Затем инициируйте запрос, результат которого вы хотите увидеть, и он появится на вкладке Сеть. Нажмите на него, а затем на вкладку Ответа. Там вы увидите точный результат. На работающем сервере проверьте журнал ошибок.

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

Просто удалите любой код, который проверяет наличие ошибки вручную, все эти 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. И проблемное место находится прямо перед частью запроса, указанной в сообщении об ошибке.

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

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

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

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

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

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

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

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

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

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

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

5. @ToolmakerSteve конечно, вы имели в виду обработчик ошибок , а не try catch