为什么这个 PDO 语句默默地失败了?

问题描述 投票:0回答:2

这是我的 PHP SQL 语句,它在 var dumping 时返回 false

$sql = $dbh->prepare('INSERT INTO users(full_name, e_mail, username, password) VALUES (:fullname, :email, :username, :password)');
$result = $sql->execute(array(
                    ':fullname' => $_GET['fullname'], 
                    ':email' => $_GET['email'], 
                    ':username' => $_GET['username'],
                    ':password' => $password_hash));
php pdo
2个回答
77
投票

TL;博士

  1. 始终在您的 PDO 连接代码中将
    PDO::ATTR_ERRMODE
    设置为
    PDO::ERRMODE_EXCEPTION
    。它会让数据库告诉你实际的问题是什么,无论是查询、服务器、数据库还是其他什么。另外,请确保您可以看到一般的 PHP 错误。
  2. 始终用问号替换 SQL 查询中的每个 PHP 变量,并使用 准备好的语句 执行查询。这将有助于避免各种语法错误。

说明

有时您的 PDO 代码会产生像

Call to a member function execute()
或类似的错误。或者即使没有任何错误,但查询并不完全相同。这意味着您的查询执行失败。

每次查询失败,MySQL 都会有一条错误消息解释原因。不幸的是,默认情况下此类错误不会转移到 PHP,您所拥有的只是上面提到的沉默或神秘的错误消息。因此,配置 PHP 和 PDO 以向您报告 MySQL 错误非常重要。一旦收到错误消息,解决问题将是轻而易举的事情。

为了获得有关问题的详细信息,请在连接后立即将以下行放入代码中

$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );

(其中

$dbh
是您的 PDO 实例变量的名称)或者 - 更好 - 添加此参数作为 connection option。之后,所有数据库错误都将被转换为 PDO 异常,如果单独放置,将与常规 PHP 错误一样。

收到错误信息后,您必须阅读并理解它。这听起来太明显了,但学习者往往会忽略错误信息的含义。然而大多数时候它很直接地解释了问题:

  • 比如说,如果它说一个特定的表不存在,你必须检查拼写、拼写错误、字母大小写。您还必须确保您的 PHP 脚本连接到正确的数据库
  • 或者,如果它说 SQL 语法有错误,那么你必须检查你的 SQL。而问题点就在before错误消息中引用的查询部分。

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


请注意,为了查看 PDO 错误,您必须能够查看一般的 PHP 错误。为此,您必须根据站点环境配置 PHP:

  • development 服务器上,在屏幕上显示错误非常方便,必须打开显示错误:

      error_reporting(E_ALL);
      ini_set('display_errors',1);
    
  • live 站点上时,所有错误都必须 logged,但绝不会向客户显示。为此,以这种方式配置 PHP:

      error_reporting(E_ALL);
      ini_set('display_errors', 0);
      ini_set('log_errors', 1);
    

注意

error_reporting
应该一直设置为
E_ALL

还请注意,尽管有常见的错觉,不必使用 try-catch 来报告错误。 PHP 会以更好的形式向您报告 PDO 错误。未捕获的异常对开发非常有利,但是如果你想显示一个自定义的错误页面,仍然不要为此使用 try catch,而只需设置一个 custom error handler。简而言之,您不必将 PDO 错误视为特殊错误,而是将它们视为代码中的任何其他错误。

附言
有时没有错误,但也没有结果。那么这意味着,没有符合您条件的数据。所以你不得不承认这个事实,即使你可以发誓数据和标准都是对的。他们不是。你必须再次检查它们。我有一个简短的回答,可以帮助您查明匹配问题,使用 PDO 匹配数据库中的行有问题。只需按照此说明和链接的教程逐步操作,即可解决您的问题或对 Stack Overflow 提出可回答的问题。


1
投票

前段时间我遇到了同样的问题,没有看到来自 mysql 的任何错误消息。经过研究发现问题与PHP本身无关,而是与mysql服务器配置有关。变量 lc_messages_dir 的默认值指向不存在的目录。在mysqld.cnf中添加一行后,重启mysql服务器,终于可以看到报错信息了。对我来说,以下是正确的:

lc_messages_dir=/usr/share/mysql

在mysql参考手册中有描述:https://dev.mysql.com/doc/refman/5.7/en/error-message-language.html

© www.soinside.com 2019 - 2024. All rights reserved.