如何在CakePHP的JOIN条件下使用CONCAT?

时间:2016-11-10 21:33:26

标签: php cakephp

我正在开发一个CakePHP 3.0后端,我有以下表格:' prescriptions '和' profils '(名字是法语)。

'处方'的外键指向“个人资料”: prescriptions.profils_id

'profils'有两个可以搜索的字段:'nom'和'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 具有搜索操作,用户可以在其中设置各种过滤器。我正在处理的那些允许他在拥有该处方的人(Profil)的名字的子串之后搜索处方。

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

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]:找不到列:1054未知列   'on clause'中的'profils.nom'

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

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

这显然不是一个非常有趣的CONCAT,但它确实有效。当我使用两个字段时,错误才会上升:第二个字段不使用别名Profils,而是使用表名'profils'。

我已经坚持这个错误几个小时了,我会很感激我在这里做错了什么。

1 个答案:

答案 0 :(得分:1)

使用的语法不支持

您正在使用的语法是支持

等结构
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'
            );
    });

另见