如何在 CakePHP 中使用别名查询关联?

How to query associations using an alias in CakePHP?

我在 CakePHP 3 中有以下查询,用于对任务实体进行搜索:

<?php

    public function search($q = "")
    { 
        $tasks = TableRegistry::getTableLocator()->get('Tasks')->find()
            ->where(function (QueryExpression $exp, Query $query) use ($q) {
                return $exp->or_(function (QueryExpression $or) use ($query, $q) {
                    $or->like('Tasks.name', '%' . $q . '%');
                    $or->like('Asset.name', '%' . $q . '%');
                    $or->like('AssignedToUsers.first_name', '%' . $q . '%');
                    $or->like('AssignedToUsers.last_name', '%' . $q . '%');
                    $or->like($query->func()->concat([
                        'AssignedToUsers.first_name' => 'identifier',
                        "' '" => 'literal',
                        'AssignedToUsers.last_name' => 'identifier'
                    ]), '%' . $q . '%');
                    return $or;
                });
            })
            ->contain(["Asset", "Asset.AssignedToUsers", "AssignedToUsers"])
            ->limit(5)
            ->order(["Tasks.modified" => "DESC"]);
    }

任务 table 与资产和 AssignedToUsers table 相关联,如下所示:

<?php

public function initialize(array $config)
{
    $this->belongsTo('Asset', [
        'className' => 'Assets',
        'foreignKey' => 'asset_id',
        'joinType' => 'LEFT'
    ]);
    $this->belongsTo('AssignedToUsers', [
        'className' => 'Users',
        'foreignKey' => 'assigned_to_user_id',
        'joinType' => 'LEFT'
    ]);
}

然后资产 table 也有一个 AssignedToUsers 关联:

<?php

public function initialize(array $config)
{
    $this->belongsTo('AssignedToUsers', [
        'className' => 'Users',
        'foreignKey' => 'assigned_to_user_id',
        'joinType' => 'LEFT'
    ]);
}

当前查询对 AssignedToUsers 的名字和姓氏进行串联搜索。但是我需要让它也包括搜索 Asset.AssignedToUsers 名字和姓氏。

如果我从搜索中的包含中删除 AssignedToUsers 关联,查询将搜索 concat 中的 Asset.AssignedToUsers 名字和姓氏字段,所以我假设 cake 无法分辨两者之间的区别AssignedToUsers 和 Asset.AssignedToUsers.

有没有一种方法可以在 contain() 调用中为 AssignedToUsers 关联设置别名,以便我可以分别查询与任务和资产关联的版本 AssignedToUsers?或者还有其他方法可以执行此查询吗?

提前致谢!

您不能在单个查询中多次使用相同的别名,这首先是一个 SQL 限制,最后一点不受 CakePHP 支持。也不支持即时更改别名。

为了包含数据,您可以尝试不同的策略,特别是 select 策略,该策略将在单独的查询中检索关联数据,而不是将其加入。对于过滤,您可以使用自定义连接使用自定义别名,大致如下:

->where(function (QueryExpression $exp, Query $query) use ($q) {
    return $exp->or_(function (QueryExpression $or) use ($query, $q) {
        // ...
        $or->like(
            $query->func()->concat([
                'AssetAssignedToUsers.first_name' => 'identifier',
                "' '" => 'literal',
                'AssetAssignedToUsers.last_name' => 'identifier'
            ]),
            '%' . $q . '%'
        );
        
        return $or;
    });
})
->join([
    'table' => 'users',
    'alias' => 'AssetAssignedToUsers',
    'type' => 'LEFT',
    'conditions' => 'AssetAssignedToUsers.id = Asset.assigned_to_user_id',
])
->contain([
    'Asset',
    'Asset.AssignedToUsers' => [
        'strategy' => \Cake\ORM\Association::STRATEGY_SELECT,
    ],
    'AssignedToUsers',
])

另一种选择是重命名一个甚至所有关联,例如在它们前面加上 parents 名称,如 TasksAssignedToUsersAssetAssignedToUsers

另见