如何在Cakephp 3中调用PDOStatement :: nextRowset()

时间:2017-02-10 11:52:35

标签: php mysql cakephp pdo cakephp-3.0

我创建了一个程序,其中有两个select语句正在运行。

$stmt = $this->_connection->execute("CALL myFunction(:user_id)", [
    'user_id' => $userId
]);

但是当我试图像这样调用nextRowset()时

$stmt->nextRowset();

它给我错误

  

调用未定义的方法Cake \ Database \ Log \ LoggingStatement :: nextRowset()

所以,我的问题是如何调用Cakephp 3中的nextRowset()

1 个答案:

答案 0 :(得分:2)

鉴于所有核心语句类在某些时候都扩展\Cake\Database\Statement\StatementDecorator,您可以通过\PDOStatement访问基础本地StatementDecorator::getInnerStatement()对象,如:

while ($stmt instanceof StatementDecorator) {
    $stmt = $stmt->getInnerStatement();
}

if (!($stmt instanceof \PDOStatement)) {
    throw new \RuntimeException('Expected an instance of \PDOStatement');
}

然后你可以使用标准的PDO语句程序,比如在循环中迭代行集:

do {
    $rowset = $stmt->fetchAll(PDO::FETCH_ASSOC);
    // ...
} while ($stmt->nextRowset());

正如评论中已经提到的,另一种方法是实现自己的语句类(并使您的代码期望该具体实现的实例)。对于跨数据库兼容性,您必须实现四个不同的语句,加上四个驱动程序,您将重新实现\Cake\Database\Driver::prepare(),因为这是生成语句实例的地方。

此外,如果您想支持查询日志记录,则必须创建自定义连接类并覆盖\Cake\Database\Connection::prepare()\Cake\Database\Connection::_newLogger(),因为这是驱动程序生成的语句被包装的位置如果启用了查询日志记录,则\Cake\Database\Log\LoggingStatement

我想说如果你想要支持的只是内置驱动程序,那么期待\Cake\Database\Statement\StatementDecorator个实例可能是目前更好的选择,即使它并不是太好了。您可能希望suggest adding functionality推进多行集语句作为增强功能,但不确定是否会对它有太多支持。

另见