为了账号安全,请及时绑定邮箱和手机立即绑定

参考 - 有关PDO的常见问题解答

参考 - 有关PDO的常见问题解答

PHP
拉莫斯之舞 2019-05-29 15:39:04
参考 - 有关PDO的常见问题解答这是什么?这是有关PHP数据对象的常见问题列表为什么是这样?由于PDO具有常规PHP用户不知道的某些功能,因此在PDO中有关预准备语句和错误处理的问题非常频繁。所以,这只是一个可以找到它们的地方。我该怎么办?如果您的问题已与此列表密切相关,请在下面找到您的问题并将修复程序应用于您的代码。对其他问题进行简要介绍也是一个好主意,让自己为其他常见陷阱做好准备。列表PDO查询失败但我看不到任何错误。如何从PDO获取错误消息?如何在LIKE运算符中使用预处理语句?如何为IN()运算符创建预准备语句?我可以使用PDO预处理语句来绑定标识符(表或字段名称)或语法关键字吗?PDO准备语句在LIMIT语句中导致错误也可以看看参考 - 这个符号在PHP中意味着什么?参考 - 这个错误在PHP中意味着什么?参考 - 什么是变量范围,哪些变量可从哪里找到,哪些是“未定义变量”错误?
查看完整描述

3 回答

?
守候你守候我

TA贡献1802条经验 获得超10个赞

PDO查询失败但我看不到任何错误。如何从PDO获取错误消息?

为了能够看到数据库错误,必须将PDO errmode设置为异常。异常在许多方面优于常规错误:它们总是包含堆栈跟踪,可以使用try..catch捕获它们或使用专用错误处理程序处理它们。甚至未处理,它们充当常规PHP错误,提供所有重要信息,遵循站点范围的错误报告设置。

请注意,将此模式设置为连接选项将使PDO也会在连接错误上抛出异常,这非常重要。
因此,这是一个以正确方式创建PDO连接的示例:

$dsn = "mysql:host=$host;dbname=$db;charset=utf8";$opt = array(
    PDO::ATTR_ERRMODE            => PDO::ERRMODE_EXCEPTION,
    // other options );$pdo = new PDO($dsn, $user, $pass, $opt);

通过这种方式连接,您将始终收到查询执行期间发生的所有数据库错误的通知。请注意,您必须能够查看PHP错误。在实际站点上,您必须查看错误日志,因此必须进行设置

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

在本地开发服务器上,可以在屏幕上出错:

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

当然,您永远不应该@在PDO语句前面使用错误抑制operator()。

此外,由于许多不好的例子告诉你将每个PDO语句包装成try..catch块,我必须做一个明确的说明:

请勿使用try..catch运算符来回显错误消息。未捕获的异常已经非常出色,因为它的行为与其他PHP错误的行为方式相同 - 因此,您可以使用站点范围的设置来定义行为 - 因此,您将获得没有此无用代码的错误消息。 虽然无条件回复的错误消息可能会向潜在的攻击者泄露一些敏感信息,但却会使诚实的访问者感到困惑。

  • 一个自定义异常处理程序可以在以后添加,但不是必需的。特别是对于新用户,建议使用未处理的异常,因为它们提供的信息非常丰富,有用且安全。

  • try..catch说,回滚事务-只有当你要处理错误本身。


查看完整回答
反对 回复 2019-05-29
?
幕布斯6054654

TA贡献1876条经验 获得超7个赞

PDO准备语句导致LIMIT子句出错

出于兼容性目的,PDO将仅通过用实际数据替换占位符来模拟预准备语句,而不是单独将它们发送到服务器,除非另有说明。使用“lazy”绑定(在execute()中使用数组),PDO会将每个参数视为字符串。因此,准备好的LIMIT ?,?查询将成为LIMIT '10', '10'导致查询失败的无效语法。

这个问题也可以解决

  • 通过关闭仿真模式(因为MySQL可以正确排序所有占位符):

    $conn->setAttribute( PDO::ATTR_EMULATE_PREPARES, false );
  • 通过显式绑定和设置正确的类型(PDO :: PARAM_INT):

    $stm = $pdo->prepare('SELECT * FROM table LIMIT ?, ?');$stm->bindValue(1, $limit_from,PDO::PARAM_INT);
    $stm->bindValue(2, $per_page,PDO::PARAM_INT);$stm->execute();$data = $stm->fetchAll();


查看完整回答
反对 回复 2019-05-29
?
达令说

TA贡献1821条经验 获得超6个赞

如何在LIKE运算符中使用预处理语句?

准备好的语句只能代表完整的数据文字。不是文字的一部分,也不是复杂的表达,也不是标识符。但只是字符串或数字。所以,一个非常常见的陷阱是这样的查询:

$sql = "SELECT * FROM t WHERE column LIKE '%?%'";

如果你仔细思考这个问题,你就会明白,在单引号内部,问号会成为一个文字问号,而对准备好的语句没有任何特殊意义。

因此,必须使用预准备语句发送完整的字符串文字。有两种可能的方法:

  • 要么首先准备FULL表达式:

    $name = "%$name%";$stm  = $pdo->prepare("SELECT * FROM table WHERE name LIKE ?");$stm->execute(array($name));$data = $stm->fetchAll();
  • 或在查询中使用连接

    $sql = "SELECT * FROM t WHERE column LIKE concat('%',?,'%')";

虽然后者看起来太臃肿了。


查看完整回答
反对 回复 2019-05-29
  • 3 回答
  • 0 关注
  • 418 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信