如何使用 CakePHP 查询生成器生成 SQL 函数调用?

Posted

技术标签:

【中文标题】如何使用 CakePHP 查询生成器生成 SQL 函数调用?【英文标题】:How to generate SQL function calls with the CakePHP query builder? 【发布时间】:2015-08-30 23:56:33 【问题描述】:

我有一个作者的全名列,并希望将姓氏提取到另一列中。我使用以下原始 SQL 来做到这一点:

SELECT name,
SUBSTRING_INDEX(`name`, ' ', -1) AS `surname`
FROM qr.authors;

输出:

Cookbook 在“使用 SQL 函数”下说:

除上述函数外,func()方法可用于创建任何通用SQL函数,如year、date_format、convert等。

但是如何通过 func() 方法创建这个 SUBSTRING_INDEX 函数,以便我可以将它与 Cakephp 查询构建器一起使用?

【问题讨论】:

【参考方案1】:

函数构建器带有预定义的方法/函数

FunctionsBuilder 类附带了一堆现成的方法/函数供您使用,如sum()count()concat()dateDiff()now() 等。您可以找到支持的函数的完整列表以及如何使用它们的示例in the Cookbookthe API docs

任意函数只需调用即可构建

FunctionsBuilder 类使用魔术方法 __call 处理程序来构建任意 SQL 函数表达式,因此如果您的函数没有现成的方法,您可以“调用”您的 SQL 函数:

$query = $this->SomeTable->find();

$func = $query->func()->substring_index([
    'name' => 'identifier',
    ' ',
    -1 => 'literal'
]);
$query->select([/* ... */, 'surname' => $func]);

这应该很容易解释,魔术方法名称是 SQL 函数名称,传递的数组包含应该传递给函数的参数,在这种情况下,第一个和最后一个参数被定义为处理作为标识符分别作为文字,因此两者都直接插入到查询中,即不是作为将被转义的绑定参数!

标识符 1 将另外受制于可能的自动标识符引用,即 name 将转换为例如 `name`"name"[name],具体取决于使用的数据库驱动程序。第二个参数也可以是文字(例如通过'" "'),我只是没有将它设置为一个例子。不这样做会导致值被绑定/转换为字符串。

生成的编译 SQL 将如下所示:

substring_index(name, :c0, -1)

最终会被执行为

substring_index(name, ' ', -1) 

处理非硬编码数据,例如用户输入

当使用非硬编码的数据时,即动态的,或可能发生变化的数据,确保在必要时在第二个参数中定义正确的类型进行转换/转义,如integer,@ 987654342@ 等。为了使其正常工作,您必须对列名值使用标识符表达式,否则在使用 'xyz' => 'identifier' 语法时将忽略第二个参数:

$func = $query->func()->substring_index(
    [
        new \Cake\Database\Expression\IdentifierExpression('title'),
        ' ',
        $userInput,
    ],
    [
        null,     // no typecasting for the first argument
        'string', // second argument will be bound/casted as string
        'integer' // third argument will be bound/casted as integer
    ]
);

类型将通过数字索引匹配,第一个将被忽略,因为它是一个表达式,因此只传递null

你甚至可以使用原始表达式

在您的情况下,您传递安全的硬编码值,这些值不需要作为绑定参数插入到查询中,并且SUBSTRING_INDEX 不是任何方言所涵盖的函数随 CakePHP 一起提供,您甚至可以使用原始查询来代替 - 但是您将失去在自定义方言中转换表达式的能力,并且自动标识符引用也将不再适用,所以只有在您知道自己在做什么的情况下才这样做!

$query->newExpr('SUBSTRING_INDEX(`name`, "", -1)')

另见

Cookbook > Database Access & ORM > Query Builder > Using SQL functions API > \Cake\Database\Query::newExpr()

【讨论】:

以上是关于如何使用 CakePHP 查询生成器生成 SQL 函数调用?的主要内容,如果未能解决你的问题,请参考以下文章

cakephp烤

尝试将 sql 查询详细说明到 cakephp 时总是出错;如何转换这个?

如何在 jquery 中获取 FormHelper::postLink() 在 Cakephp4 中使用选项 'block' => true 生成的表单?

如何执行由 python-sql 查询生成器形成的查询?

如何使用doctrine查询生成器编写此sql查询?

如何修改hibernate生成的SQL查询?