mysqli_fetch_array():参数#1必须是mysqli_result类型。如何处理mysqli问题?

2022-02-21 00:00:00 php mysqli error-reporting

在我的本地/开发环境中,MySQLi查询执行正常。但是,当我将其上传到我的Web主机环境时,收到以下错误:

致命错误:调用.中的非对象上的成员函数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执行查询,结果正常。


解决方案

TL;DR

  1. 您的mysqli连接代码中始终有mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);。它将让MySQL告诉您实际问题是什么,是查询问题、服务器问题、数据库问题还是其他问题。
  2. 始终使用问号替换SQL查询中的每个PHP变量,并使用prepared statement执行查询。这将有助于避免各种语法错误。

说明

有时您的MySQLi代码会产生类似mysqli_fetch_assoc() expects parameter 1 to be mysqli_result, boolean given...Call to a member function bind_param()...或类似的错误。或者甚至没有任何错误,但是查询并不都能正常工作。这意味着您的查询执行失败。

每次查询失败时,MySQL都会有一条错误消息解释原因。不幸的是,默认情况下,此类错误不会传输到PHP,您得到的只是上面提到的一条隐晦的错误消息。因此,配置PHP和MySQLi向您报告MySQL错误非常重要。一旦您收到错误消息,修复它将是小菜一碟。

如何在MySQLi中获取错误信息

首先,在所有环境中,MySQLi连接之前始终要有此行:

mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);

之后,所有MySQL错误都将转换为PHP异常。未捕获的异常反过来会导致PHP致命错误。因此,在出现MySQL错误的情况下,您将得到一个常规的PHP错误。这将立即使您了解错误原因。堆栈跟踪将引导您找到发生错误的确切位置。

如何在不同环境下配置PHP

以下是我关于PHP error reporting的文章要点: 在开发服务器和实时服务器上报告错误必须不同。在开发服务器上,将错误显示在屏幕上很方便,但在实时服务器上,必须改为记录错误消息,以便您稍后可以在错误日志中找到它们。

因此,您必须将相应的配置选项设置为以下值:

  • 在开发服务器上

  • error_reporting应设置为E_ALL值;

  • log_errors应设置为1(开发PC上也可以有日志)

  • display_errors应设置为1

  • 在生产服务器上

  • error_reporting应设置为E_ALL值;

  • log_errors应设置为1

  • display_errors应设置为0

实际使用方法

只需删除所有手动检查错误的代码,or die()if ($result)等等。只需立即编写数据库交互代码即可:

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

再次,周围没有任何条件。如果发生错误,它将被视为代码中的任何其他错误。例如,在开发PC上,它只会出现在屏幕上,而在实时站点上,它会为程序员记录下来,而为了方便用户,您可以使用错误处理程序(但这是另一回事,这与MySQLi的主题不同,但您可以在上面链接的文章中了解到这一点)。

如何处理收到的错误消息

首先,您必须找到问题查询。错误消息包含文件名和错误发生位置的行号。对于简单的代码就足够了,但是如果您的代码使用的是函数或类,您可能需要遵循堆栈跟踪来定位问题查询。

收到错误消息后,您必须阅读并理解它。这听起来即使不是居高临下,也太明显了,但是学习者经常忽略这样一个事实,即错误消息不仅仅是一个警报信号,它实际上包含了对问题的详细解释。您只需阅读错误消息并修复问题。

  • 比方说,如果它显示某个表不存在,您必须检查拼写、打字错误和字母大小写。此外,您还必须确保PHP脚本连接到正确的数据库
  • 或者,如果它显示SQL语法中有错误,那么您必须检查您的SQL。并且问题点就在错误消息中引用的查询部分之前。

如果您不理解错误消息,请尝试在Google上搜索它。在浏览结果时,请坚持解释错误的答案,而不是直截了当地给出解决方案。解决方案可能在您的特定情况下不起作用,但解释将帮助您了解问题并使您能够自行解决问题。

您还必须信任错误消息。如果它说令牌的数量与绑定变量的数量不匹配,那么就是。缺少的表或列也是如此。如果可以选择,无论是您自己的错误还是错误消息,始终坚持前者。这听起来又一次居高临下,但这个网站上的数百个问题证明了这个建议非常有用。

关于错误报告,千万不要做的事情列表

  • 切勿使用错误抑制运算符(@)!这会使程序员无法读取错误消息,因此无法修复错误
  • 请勿使用die()echo或任何其他功能在屏幕上无条件打印错误信息。PHP可以自行报告错误,并根据环境的不同以正确的方式进行报告-因此只需将其留给PHP即可。
  • 请勿添加条件手动测试查询结果(如if($result))。启用错误异常后,此类条件将毫无用处。
  • 请勿使用try..catch运算符回显错误消息。应该使用此运算符执行一些错误处理,如事务回滚。但是千万不要仅仅用它来报告错误--正如我们在上面了解到的,PHP已经可以通过正确的方式做到这一点。

P.S.
有时没有错误,但也没有结果。则表示数据库中没有与您的条件匹配的数据。在这种情况下,您必须承认这一事实,即使您可以发誓数据和标准都是正确的。他们不是。您必须再次检查它们。

我有一篇文章可以在这个问题上提供帮助,How to debug database interactions。虽然它是为PDO编写的,但原理是相同的。只需一步一步地按照这些说明操作,即可解决您的问题或提出堆栈溢出的可回答问题。

相关文章