TL;DR
- 在你的 mysqli 连接代码中总是有
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);。它会让 MySQL 告诉您实际的问题是什么,无论是查询、服务器、数据库还是其他问题。
- 始终用问号替换 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 已经可以做到这一点,而且是正确的。
附言
有时没有错误,但也没有结果。那么这意味着,数据库中没有符合您条件的数据。在这种情况下,您必须承认这一事实,即使您可以发誓数据和标准都是正确的。他们不是。您必须再次检查它们。
我有一篇文章可以帮助解决这个问题,How to debug database interactions。虽然是为PDO写的,但是原理是一样的。只需按照这些说明一步一步地解决您的问题或对 Stack Overflow 提出可回答的问题。