别名查询是否可以使用包含子句



我使用并集来连接两个数据集,然后使用以下查询来设置正确的分页

$paginationQuery = $this->find('all')
->contain(['EmailAddresses' => [
'foreignKey' => false,
'queryBuilder' => function($q) {
return $q->where(['Members__id' => 'EmailAddresses.member_id']);
}
]])
->select( $selectMainUnion )
->from([$this->getAlias() => $query])
->order(['Members__last_name' => 'ASC', 'Members__first_name' => 'ASC']);

我也试过

$paginationQuery = $this->find('all')
->contain(['EmailAddresses'])
->select( $selectMainUnion )
->from([$this->getAlias() => $query])
->order(['Members__last_name' => 'ASC', 'Members__first_name' => 'ASC']);

并尝试$query->loadInto($query,[电子邮件地址](;其中$query是并集的结果。

这两种方法都不会将电子邮件地址添加到$paginationQuery中。

有办法做到这一点吗?

添加以澄清代码

$selectMain =['Members.id',
'Members.member_type',
'Members.first_name',
'Members.middle_name',
'Members.last_name',
'Members.suffix',
'Members.date_joined'];
foreach($selectMain as $select) {
$selectMainUnion[] = str_replace('.', '__', $select);
}
$this->hasMany('EmailAddresses', [
'foreignKey' => 'member_id',
'dependent' => true,
]);

查看DebugKit SQL日志中的SQL,没有引用EmailAddresses表。

通常,无论查询FROM子句是表还是子查询,容器都可以正常工作。然而,要做到这一点,需要选择所需的主键和/或外键字段,并且它们的格式正确。

默认情况下,CakePHP的ORM查询会自动对所选字段进行别名,即它们像Alias.field AS Alias__field一样被选中。因此,当Alias是一个子查询时,那么Alias.field不存在,您必须选择Alias.Alias__field。因此,使用自动别名,您对Members__id的选择将转换为Members.Members__id AS Members__Members__id,而Members__Members__id不是ORM所理解的,它在您的实体中最终会变成Members__id,而热切的加载器会期望id,即用于注入查询的hasMany相关记录的结果的主键的名称(这发生在单独的查询中(,您的自定义queryBuilder对此没有帮助,因为注入之后会在PHP级别上进行。

长话短说,为了解决这个问题,您可以更改联合查询的字段的选择方式,即确保它们不使用别名进行选择,这样就根本不需要更改分页查询字段:

$fields = $table->getSchema()->columns();
$fields = array_combine($fields, $fields);
$query->select($fields);

这将创建一个格式为['id' => 'id', ...]的字段列表,看起来有点奇怪,但它是有效的(例如,只要没有因联接表而产生的歧义(,SQL将类似于id AS id,因此您的分页查询可以简单地引用类似Members.id的字段。

另一种方法是选择子查询的别名,即不仅选择Member__id,ORM在应用自动别名时将其转换为Member__Member__id,而且使用Members.Member__id,如:

[
'Member__id' => 'Members.Member__id',
// ...
]

这样就不会发生自动别名,在SQL级别上,它会选择类似Members.Member__id AS Member__id的字段,并且该字段在实体中最终会变成id,热切的加载器会找到它,并可以使用它来注入关联的记录。

最新更新