CakePHP 3 - 查询对象的访问参数

CakePHP 3 - access params of Query object

在 CakePHP 中 3.x 我可以这样做:

$Substances = TableRegistry::get('Substances');
$query = $Substances->find()->where($where_conditions)->select(['id']);
debug($query); 

这会显示查询对象。

如果我想获得 SQL 字符串,我可以使用 debug($query->sql());。这将为我提供带有任何参数占位符的 SQL 字符串,例如

SELECT ... WHERE ... in (:c0,:c1,:c2))

当使用 debug($query) 时,我可以看到 :c0:c1 等的值:

'params' => [
    ':c0' => [
        'value' => (int) 47,
        'type' => 'smallinteger',
        'placeholder' => 'c0'
    ],
    ':c1' => [
        'value' => (int) 93,
        'type' => 'smallinteger',
        'placeholder' => 'c1'
    ],
    ':c2' => [
        'value' => (int) 845,
        'type' => 'smallinteger',
        'placeholder' => 'c2'
    ],
    ':c3' => [
        'value' => (int) 354,
        'type' => 'smallinteger',
        'placeholder' => 'c3'
    ]
]

但是,我无法在 debug 语句之外访问它们。例如 $query->params()$query['params'] 没有给我参数——它会出错。我希望能够将此数组传递给自定义函数,那么如何访问它?

这很奇怪,因为我可以使用 debug($query->sql()) 来获取 SQL 字符串,而 params 只是该对象中的另一个东西,但似乎无法访问.

我读过 How to get params from query object in CakePHP 3 但我认为这是一个不同的问题,因为它与在 debug 语句中看不到值有关,因为 debug 会默认深度提供。

我想这样做的原因是因为我希望能够执行 CREATE TABLE AS 查询,将 SELECT 语句的值写入新的 table ( 重要提示: 请参阅 this link 了解其在原版 MySQL 中的工作原理示例。我无法弄清楚如何使用 Cake 中的 ORM 来做到这一点,所以正计划编写一个自定义函数。但是我需要能够访问 SQL 以及绑定的参数,以便可以在我自己的函数中执行查询。

如果您知道我可以使用 ORM 执行 CREATE TABLE AS 查询的解决方案,我仍然有兴趣了解这个。但是我想知道 params 是否也可以在 debug() 之外访问。

前提:我其实不明白你为什么需要参数

无论如何。您需要的信息由查询ValueBinder对象

存储

所以你可以简单地做

$params = $query->getValueBinder()->bindings();
debug($params);

但出于某种原因,这会给你一个空数组。我的猜测是查询首先需要某种初始化。

事实上如果你运行

debug($query);
$params = $query->getValueBinder()->bindings();
debug($params);

您会看到您的参数。我想会有比我更专业的人来给个完整的解释

编辑: 我注意到调试 $query 调用 $query->sql(),后者又调用 conection->compileQuery();

所以你可以做到

$query->sql(); // you need this to compile the query
               // and generate the bindings
$params = $query->getValueBinder()->bindings();

CakePHP 不提供创建此类 CREATE TABLE AS 语句的具体方法,因此您必须自己构建它。

使用查询对象 sql() 方法编译问题中显示的查询非常简单,正如 arilia 已经提到的那样,您将能够访问绑定到该查询的参数 after 被编译。

有了编译的 SQL 和关联的值绑定器,您可以将其与自定义原始查询结合起来构建您的 CREATE TABLE AS 语句。您需要做的就是使用已编译的 SQL 准备一个新语句,并通过它自己的 attachTo() 方法附加值绑定器。

您可能还需要做的一件事是在 select() 中定义自定义别名,否则您最终会以 Substances_id 的形式选择(和创建)列.

$Substances = TableRegistry::get('Substances');

$selectQuery = $Substances
    ->find()
    ->where($where_conditions)
    ->select(['id' => 'id']); // < create aliases as required

// compile the ORM query, this will populate the value binder
$selectSql = $selectQuery->sql();

// combine table creation SQL and compiled ORM query in a single statement
$createStatement = $Substances
    ->getConnection()
    ->prepare('CREATE TABLE dynamic_table AS ' . $selectSql);

// attach the ORM querys value binder, binding all its values to the given statement
$selectQuery->getValueBinder()->attachTo($createStatement);

$success = $createStatement->execute();

这应该创建 SQL 类似于:

CREATE TABLE dynamic_table AS 
    SELECT 
      id AS id
    FROM 
      substances Substances 
    WHERE 
      ...

另见