Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/238.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 参考—;关于PDO的常见问题 这是什么?_Php_Pdo - Fatal编程技术网

Php 参考—;关于PDO的常见问题 这是什么?

Php 参考—;关于PDO的常见问题 这是什么?,php,pdo,Php,Pdo,这是一个关于PHP数据对象的常见问题列表 为什么会这样? 由于PDO有一些普通PHP用户所不知道的特性,因此关于PDO中准备好的语句和错误处理的问题非常常见。所以,这只是一个可以找到所有这些东西的地方 我在这里该怎么办? 如果您的问题已通过此列表投票,请在下面找到您的问题并将修复应用于您的代码。简单看看其他问题也是一个好主意,让自己为其他常见的陷阱做好准备 名单 另见 PDO查询失败,但我看不到任何错误。如何从PDO获取错误消息? 为了能够看到数据库错误,必须设置为exce

这是一个关于PHP数据对象的常见问题列表

为什么会这样? 由于PDO有一些普通PHP用户所不知道的特性,因此关于PDO中准备好的语句和错误处理的问题非常常见。所以,这只是一个可以找到所有这些东西的地方

我在这里该怎么办? 如果您的问题已通过此列表投票,请在下面找到您的问题并将修复应用于您的代码。简单看看其他问题也是一个好主意,让自己为其他常见的陷阱做好准备

名单
另见

PDO查询失败,但我看不到任何错误。如何从PDO获取错误消息? 为了能够看到数据库错误,必须设置为exceptions。异常在许多方面都比常规错误好:它们总是包含堆栈跟踪,可以使用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语句前面使用错误抑制运算符(
@

此外,由于许多糟糕的示例告诉您将每个PDO语句包装到
try..catch
块中,因此我必须做一个明确的说明:

不要使用try..catch操作符只是为了回显错误消息。未捕获异常在这方面已经很好了,因为它的作用方式与其他PHP错误相同-因此,您可以使用站点范围的设置来定义行为-因此,您将收到没有此无用代码的错误消息。而无条件回显的错误消息可能会向潜在攻击者透露一些敏感信息,但会使诚实的访问者感到困惑

  • 可以稍后添加,但不是必需的。特别是对于新用户,建议使用未经处理的异常,因为这些异常信息丰富、有用且安全
  • 仅当您要处理错误本身时才使用
    try..catch
    ,例如回滚事务
如何将准备好的语句与LIKE运算符一起使用? 准备好的语句只能表示完整的数据文本。不是文字的一部分,也不是复杂表达式,也不是标识符。但不是字符串就是数字。因此,一个非常常见的陷阱是这样的查询:

$sql = "SELECT * FROM t WHERE column LIKE '%?%'";
如果你仔细思考一下这个问题,你就会明白,在单引号中,问号变成了一个字面问号,对准备好的语句没有任何特殊意义

所以,必须使用prepared语句发送完整的字符串文本。有两种可能的方法:

  • 请先准备完整表达式:

    $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('%',?,'%')";
    
尽管后者似乎过于臃肿。

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

这个问题也可以解决

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

  • 通过显式绑定和设置适当的类型(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();
    

我认为这不适合这样做。这不是常见问题解答网站。你可以把它放在你的网站上。至少这些帖子的所有权应该改为“社区维基”,我发现一个3年的52k代表用户会发布这样的帖子,并给出5个自己的答案,这是非常令人惊讶的。您有足够的rep来编辑PDO标记wiki。这是属于那里的。到处都是反对票。标记关闭。您介意更改此问题和社区Wiki所有答案的所有权吗?这正是CW的用意。仅供参考,这个问题目前正在拆分成单独的帖子进行讨论,我想这些问题将非常有用。我支持创建规范问题或“大师级”问题的努力,但我不得不同意,像这样的一组问题不符合SO的格式,就像所有这些问题都是由一个真正寻求答案的人放在一篇帖子中一样。这应该不言而喻,但在大多数情况下,你会想避开
%
\uu
和任何其他引擎支持的通配符,然后再将其放入查询中。@DCoder:+1,只是为了完整起见,并且因为这是一个参考问题:
addcslashes($name,%\\\)。谢谢,但这只是且仅限于在PDO中限制使用时?
$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();