【问题标题】:PHP PDO::FETCH_LAZY - not creating object variable names as they are accessedPHP PDO::FETCH_LAZY - 在访问对象变量名时不创建它们
【发布时间】:2013-01-22 15:32:07
【问题描述】:

我正在使用 PDO,但无法理解 PDO::FETCH_LAZY。在 PHP 手册中,它说“...PDO::FETCH_LAZY 在访问对象变量名时创建它们...”。我有这个代码来测试这个:

b类{ 函数 __construct(){} } $b = 新 b(); $pdo = new PDO('mysql:host=localhost;dbname=test', 'username', 'pssword'); //testtable{id int, title varchar, msg varchar, time varchar} $res = $pdo->query("SELECT * FROM testtable limit 1"); $b = $res->fetch(PDO::FETCH_LAZY); 回声$b->味精; var_dump($b);

这应该只打印带有 1 个属性 msg 的对象 b。但相反,输出是这样的:

这是一条示例消息。 对象(PDORow)#6(5){ [“查询字符串”]=> string(31) "SELECT * FROM testtable limit 1" [“身份证”]=> 字符串(1)“1” [“标题”]=> string(5) "示例标题" [“味精”]=> string(13) "这是一条示例消息。" [“时间”]=> 字符串(7)“1232123” }

任何人都可以对此有所了解吗?谢谢。

【问题讨论】:

  • 很确定var_dump($b) 会导致它访问所有属性并加载它们。
  • 只是好奇。您使用的是什么数据库后端?

标签: php pdo


【解决方案1】:

PDORow 是一个内部类,文档记录很差。 甚至不是in the manual(搜索结果)。

查看 PDORow 的唯一方法是 FETCH_LAZY:

$stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
$stmt->bindValue(':id', 1, PDO::PARAM_INT);
$stmt->execute();
$lazy = $stmt->fetch(PDO::FETCH_LAZY);

有趣的是它的所有属性都是公开的。第一个,“queryString”,与 sql 查询相关联。它是某种代理。

您可以将它重用于进一步的语句,以获取完整的对象。获取 PDORow(几乎)不会增加内存使用量。它不是可序列化的,并且在其上调用未定义的属性不会引发错误。

More about it on phpdelusions.net

当使用 fetch lazy 时从 PDO 返回的对象不是 stdclass 对象,它们是 pdorow 类型并且具有一些神奇的特性,包括延迟数据获取 - 这对于 pdo _ 驱动程序的设置方式有点模糊

You can follow this interesting discussion 关于它。

来自 php-src,we can see that PDORow is not meant to be instantiated

You can see several details about the class in pdo_stmt.c Ctrl+F PDORow 其余部分

编辑

FETCH_LAZY 的一个可能用例是:

// get the lazy object - aka, PDORow
    $stmt = $pdo->prepare('SELECT * FROM users WHERE id = :id');
    $stmt->bindValue(':id', 100, PDO::PARAM_INT);
    $stmt->execute();
    $lazy = $stmt->fetch(PDO::FETCH_LAZY);

接下来,重复使用它:

// do whatever you please with the properties, since they're all public
   $publicProps = get_object_vars($lazy);

然后,如果需要,加载真实对象:

// loading lazy object
    $stmt = $pdo->prepare($publicProps['queryString']);
    $stmt->bindValue(':id', $publicProps['id'], PDO::PARAM_INT); 
    /** you could use a regex to get an array of parameters' names prefixed by ':' in the original queryString
    * eg, $queryString = 'SELECT * FROM users WHERE firstName = :firstName AND email = :email';
    * preg_match_all('/:[^\s]+/', $queryString, $matches);
    * would give you an array with ":firstName" and ":email"
    */
    $stmt->execute([':id' => $publicProps['id']]);
    $notLazy = $stmt->fetch();

【讨论】:

  • 更新:在会话中存储 PDORow 的功能很久以前就被删除了,因为它为漏洞利用铺平了道路。
  • 您也可以将/:\w+/ 用于包含下划线的正则表达式,因为... limit :limit,:offset 可以作为一个部分匹配,+1
【解决方案2】:

排队

$b = $res->fetch(PDO::FETCH_LAZY);

您为变量 $b 提供了新值(PDORow 对象),覆盖了 'b' 对象

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多