【问题标题】:PHP PDO: Fetching data as objects - properties assigned BEFORE __construct is called. Is this correct?PHP PDO:将数据作为对象获取 - 在调用 __construct 之前分配的属性。这个对吗?
【发布时间】:2010-05-19 01:25:19
【问题描述】:

完整的问题应该是“这是正确的还是我不能指望的错误?”

为什么这是正确的行为?

我一直在使用 PDO,尤其是直接将数据提取到对象中。这样做时我发现了这一点:

如果我直接将数据提取到这样的对象中:

$STH = $DBH->prepare('SELECT first_name, address from people WHERE 1');
$obj = $STH->fetchAll(PDO::FETCH_CLASS, 'person');

并且有一个像这样的对象:

class person {
  public $first_name;
  public $address;

  function __construct() {
    $this->first_name = $this->first_name . " is the name";
  }
}

它告诉我,在调用 __construct 之前已经分配了属性——因为所有名称都附加了“是名称”。

这是一些错误(在这种情况下我不能/不会指望它)还是这是它应该的方式。因为它目前的工作方式确实是一件非常好的事情。

更新

显然,according to one of the maintainers 这不是错误。有人在 2008 年将其作为错误发布,对此的回复是“这不是错误,请阅读文档”。

但是,我真的很想知道为什么这是正确的行为。

【问题讨论】:

    标签: php pdo


    【解决方案1】:

    经过大量阅读,我想我终于找到了答案:它是故意以这种方式工作的,你可以选择让它以其他方式工作。

    有一个名为PDO::FETCH_PROPS_LATE 的大部分未记录的 PDO 常量,您可以使用它来在对象构建后将属性提取到对象中。例如:

    $obj = $STH->fetchAll(PDO::FETCH_CLASS | PDO::FETCH_PROPS_LATE, 'person');
    

    将导致在创建对象后分配属性,因此我上面的示例根本不会修改属性。当然,关闭 PDO::FETCH_PROPS_LATE 会导致它按照我在原始问题中的示例中所述进行操作。

    维护人员似乎已经积极考虑这两种行为都可能是可取的,并为您提供了两种选择。文档甚至没有解释它——我是reading through a list of PDO constants,看到了它,然后试了一下。

    【讨论】:

    • 你可以打赌它不容易找到。我非常需要我正在写的和 orm(使用 __set)的延迟获取,虽然我几个月前读过一篇关于它的帖子,但我在谷歌上花了大约半个小时来再次挖掘关于常量的信息。感谢您提供常量列表。
    【解决方案2】:

    原因是,当您将对象序列化为数据库或字符串时,您(通常)不希望在反序列化时重新初始化属性。

    【讨论】:

      【解决方案3】:

      尝试使用 PDO::FETCH_INTO 代替 PDO::FETCH_CLASS。 From the docs:

      PDO::FETCH_INTO:更新请求类的现有实例,将结果集的列映射到类中的命名属性

      因此,您首先要创建实例,然后将实例传递给您想要的 fetch 方法。

      话虽如此,是的,在调用 __construct 之前填充 FETCH_CLASS 是相当违反直觉的。邮件列表中给出的答案是标准的复制粘贴“RTM”答案。如果 FETCH_INTO 有效,您应该打开带有建议增强功能的文档错误。

      【讨论】:

      • 我并没有试图规避这种行为 - 我认为它令人惊叹。我正在努力确保它“按预期工作”并找出“为什么”。
      • 啊,那是个好问题。不幸的是,除非您决定深入研究 PDO 源代码,否则我认为 php-internals 之外的任何人都无法回答这个问题!
      • 我已经过去 45 分钟左右......但它远远高于我的工资等级。
      • @Charles Ah, a good question then. Unfortunately I don't think anyone outside of php-internals is going to be able to answer that, unless you decide to go diving into the PDO source! 这是通过反射完成的。 php.net/manual/en/class.reflectionclass.php
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-02-17
      • 2014-10-28
      相关资源
      最近更新 更多