如何在连接条件中使用CONCAT和CakePHP?

如何在连接条件中使用CONCAT和CakePHP?,php,cakephp,Php,Cakephp,我正在开发一个CakePHP 3.0后端,其中有以下表格:“处方”和“profils”(名称为法语) “处方”有一个指向“profils”的外键:处方。profils\u id “profils”有两个可以搜索的字段:“nom”和“prenom” 关系声明如下: class PrescriptionsTable extends Table { public function initialize(array $config) { $this->tab

我正在开发一个CakePHP 3.0后端,其中有以下表格:“处方”和“profils”(名称为法语)

“处方”有一个指向“profils”的外键:处方。profils\u 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',
        ]);
    }
}
PrescriptionController有一个搜索操作,用户可以在其中设置各种过滤器。我正在处理的程序允许他在拥有处方的人的名字(Profil)的子字符串后搜索处方

因此,al可以与“阿尔伯特·杜邦”或“马克·维达尔”相提并论,但不能与“尤金·布伦”相提并论。同样地,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子句”中的“profils.nom”

我想检查查询对象,因此我尝试:

$q1->matching('Profils', function ($q) use($filter) {
                    return $q->where(["CONCAT(Profils.prenom, ' ') like" => "%$filter%"]); 
这显然不是一个很有趣的康卡特,但它是有效的。仅当我使用两个字段时,错误才会出现:第二个字段不使用别名Profils,而是使用表名“Profils”

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

所使用的语法不支持这一点 您正在使用的语法是用于支持以下结构的

TableAlias.column SQL_EXPRESSION
编译器将对表达式部分进行小写,即在可能的
TableAlias.column
标识符之后找到的所有内容,因此在您的情况下
CONCAT(Profils.prenom,
将被视为标识符,其余部分将被视为通过空格分隔的
'',Profils.nom),如
,正被视为表达式(两个表达式都没有被检查有效性),因此被小写,这就是它发生的地方,finaly查询将查找
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'
            );
    });
另见


因为它说错误在条款上的
中,所以是否存在您可能正在执行连接的地方并且可能失败?我可能错了,因为我没有CakePHP方面的经验,并且我必须在紧急情况下处理此代码。据我所知,这些文件的匹配()函数处理连接。
Profils
表是否有一个
nom
列?我必须使用“literal”而不是“identifier”,因为“identifier”类型给了我如下查询:SELECT Prescriptions.id AS
Prescriptions\u id
FROM Prescriptions Prescriptions Prescriptions LEFT join Profils ON Profils.id=(Prescriptions.profils_id)其中(Prescriptions.users_id=190和(CONCAT('identifier','identifier'))类似于'%whatever%')。无论如何,感谢您的详细回答,您拯救了我的一天:o)@christophern这不应该发生,
identifier
应该是一种方式,因为它支持自动引用。我已经用最新的CakePHP3.3.8测试了代码,效果很好。