如何在 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 名称,如 TasksAssignedToUsers
、AssetAssignedToUsers
等
另见
我在 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 名称,如 TasksAssignedToUsers
、AssetAssignedToUsers
等
另见