别名查询可以使用 contain 子句吗?
Can an aliased query use a contain clause?
我使用联合连接两个数据集,然后使用以下查询正确设置分页
$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, ['EmailAddresses']);其中 $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 table。
通常,无论查询 FROM
子句如何,包含都可以正常工作,无论是 table 还是子查询都应该无关紧要。然而,此工作的要求是所需的主要 and/or 外键字段正在 selected,并且它们的格式正确。
默认情况下,CakePHP 的 ORM 查询会自动为 selected 字段设置别名,即它们像 Alias.field AS Alias__field
一样被 selected。所以当 Alias
是子查询时, Alias.field
不存在,你必须 select Alias.Alias__field
代替。所以使用自动别名,你的 Members__id
的 select 将被转换为 Members.Members__id AS Members__Members__id
,而 Members__Members__id
不是 ORM 理解的东西,它最终会成为 Members__id
在你的实体中,热切的加载器会期望 id
而不是,即用于注入查询结果的主键的名称 hasMany
相关记录(这发生在单独的查询中) ,您的自定义 queryBuilder
对此无济于事,因为注入发生在 PHP 级别之后。
长话短说,要解决此问题,您可以更改联合查询字段的 selected 方式,即确保它们不使用别名 selected,这样分页查询字段根本不需要更改:
$fields = $table->getSchema()->columns();
$fields = array_combine($fields, $fields);
$query->select($fields);
这将创建一个格式为 ['id' => 'id', ...]
的字段列表,看起来有点古怪,但它确实有效(只要没有因为连接的 table 引起的歧义), SQL 类似于 id AS id
,因此您的分页查询可以简单地引用 Members.id
.
等字段
另一种方法是 select 子查询的别名,即不仅仅是 select Member__id
,ORM 在应用自动别名时会变成 Member__Member__id
,但使用 Members.Member__id
,例如:
[
'Member__id' => 'Members.Member__id',
// ...
]
这样就不会发生自动别名,在 SQL 级别上,它会 select 像 Members.Member__id AS Member__id
这样的字段,并且该字段最终会成为 id
实体,急切的加载程序会找到并可用于注入相关记录。
我使用联合连接两个数据集,然后使用以下查询正确设置分页
$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, ['EmailAddresses']);其中 $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 table。
通常,无论查询 FROM
子句如何,包含都可以正常工作,无论是 table 还是子查询都应该无关紧要。然而,此工作的要求是所需的主要 and/or 外键字段正在 selected,并且它们的格式正确。
默认情况下,CakePHP 的 ORM 查询会自动为 selected 字段设置别名,即它们像 Alias.field AS Alias__field
一样被 selected。所以当 Alias
是子查询时, Alias.field
不存在,你必须 select Alias.Alias__field
代替。所以使用自动别名,你的 Members__id
的 select 将被转换为 Members.Members__id AS Members__Members__id
,而 Members__Members__id
不是 ORM 理解的东西,它最终会成为 Members__id
在你的实体中,热切的加载器会期望 id
而不是,即用于注入查询结果的主键的名称 hasMany
相关记录(这发生在单独的查询中) ,您的自定义 queryBuilder
对此无济于事,因为注入发生在 PHP 级别之后。
长话短说,要解决此问题,您可以更改联合查询字段的 selected 方式,即确保它们不使用别名 selected,这样分页查询字段根本不需要更改:
$fields = $table->getSchema()->columns();
$fields = array_combine($fields, $fields);
$query->select($fields);
这将创建一个格式为 ['id' => 'id', ...]
的字段列表,看起来有点古怪,但它确实有效(只要没有因为连接的 table 引起的歧义), SQL 类似于 id AS id
,因此您的分页查询可以简单地引用 Members.id
.
另一种方法是 select 子查询的别名,即不仅仅是 select Member__id
,ORM 在应用自动别名时会变成 Member__Member__id
,但使用 Members.Member__id
,例如:
[
'Member__id' => 'Members.Member__id',
// ...
]
这样就不会发生自动别名,在 SQL 级别上,它会 select 像 Members.Member__id AS Member__id
这样的字段,并且该字段最终会成为 id
实体,急切的加载程序会找到并可用于注入相关记录。