我如何使用CONCAT连接条件与CakePHP


How can I use CONCAT in JOIN conditions with CakePHP?

我正在CakePHP 3.0后端工作,我有以下表:'处方'和'概要文件'(名称是法语)。

' prescritions '有一个指向' profiles '的外键: prescritions .profils_id

"profiles"有两个可以搜索的字段:"nom"answers"prenom"

关系是这样声明的:

class PrescriptionsTable extends Table
{    
    public function initialize(array $config)
    {
        $this->table('prescriptions');
        $this->belongsTo('Profils', [
            'foreignKey' => 'profils_id',
        ]);
     }
}
class ProfilsTable extends Table
{
    public function initialize(array $config)
    {
        $this->table('profils');
        $this->hasMany('Prescriptions', [
            'foreignKey' => 'profils_id',
        ]);
    }
}

PrescriptionsController有一个搜索操作,用户可以在其中设置各种过滤器。我正在研究的那些允许他搜索处方后的人(配置文件)的名字的子字符串拥有该处方。

因此,'al'可以匹配'Albert Dupont'或'Marc Vidal',但不能匹配' eug brown '。同样,'ert dup'应该匹配'Albert Dupont'(作为'ont Al' should',但这是另一个故事)。

search()方法的查询行如下:

$q1 = $this->Prescriptions->find()->where(['Prescriptions.users_id = ' . $userId]);
$q1->matching('Profils', function ($q) use($filter) {
                return $q->where(["CONCAT(Profils.prenom, ' ', Profils.nom) like" => "%$filter%"]);
});
[...]
return $q1->select(['id'])->toArray();

不幸的是,当我运行查询时,CakePHP抛出以下错误:

错误:SQLSTATE[42S22]: Column not found: 1054 Unknown Column的资料。Nom ' in 'on子句

我想检查查询对象,所以我尝试:

$q1->matching('Profils', function ($q) use($filter) {
                    return $q->where(["CONCAT(Profils.prenom, ' ') like" => "%$filter%"]); 

显然不是一个很有趣的CONCAT,但它可以工作。只有当我使用两个字段时,错误才会上升:第二个字段不使用别名Profils,而是使用表名"profiles"。

我已经被这个错误困了好几个小时了,我将感谢任何关于我在这里做错了什么的见解。

使用的语法不支持

你正在使用的语法是用来支持像

这样的结构的。
TableAlias.column SQL_EXPRESSION

编译器将小写表达式部分,即在可能的TableAlias.column标识符之后发现的所有内容,因此在您的情况下,CONCAT(Profils.prenom,将被视为标识符,其余部分被视为通过空格分隔,' ', Profils.nom) like,被视为表达式(都没有被检查有效性),因此被小写,这就是它发生的地方,最后查询将寻找profils.nom,它不存在,因为别名是Profils

使用表达式

你应该使用合适的表达式,它们是可移植的,可组合的,并且支持值绑定。

CakePHP提供了对各种SQL函数的支持,包括CONCAT。它还支持各种比较表达式,可以与其他表达式组合,即您可以简单地将concat函数表达式传递给like比较表达式,您应该很好:

return $q
    ->where(function ('Cake'Database'Expression'QueryExpression $exp, 'Cake'ORM'Query $query) use($filter) {
        return $exp
            ->like(
                $query->func()->concat([
                    'Profils.prenom' => 'identifier',
                    ' ',
                    'Profils.nom' => 'identifier'
                ]),
                "%$filter%",
                'string'
            );
    });

参见

  • Cookbook>数据库访问&ORM>查询生成器>使用SQL函数
  • Cookbook>数据库访问&ORM>查询生成器>高级条件
  • API> 'Cake'Database'Expression'QueryExpression::like()
  • API> 'Cake'Database'FunctionsBuilder::concat()