CakePHP 3 Query Builder 在指定 select 字段时缺少包含字段
CakePHP 3 Query Builder missing contain fields when specifying select fields
我有一个相当简单的查询,它针对包含的字段生成不同的 SQL 语句,具体取决于我是否将字段指定为 select。我知道这很令人困惑,所以我会尝试用代码来描述问题。
我设置了以下关联,它们在简单的 find()
上工作正常,但当我尝试使用 find()->select
时却不行。
集合表:
$this->belongsTo('IconMedia', [
'foreignKey' => 'icon_media_id',
'className' => 'Media'
]);
$this->belongsTo('HeroMedia', [
'foreignKey' => 'hero_media_id',
'className' => 'Media'
]);
媒体表:
$this->hasMany('CollectionsIconMedia', [
'foreignKey' => 'icon_media_id',
'className' => 'Collections'
]);
$this->hasMany('CollectionsHeroMedia', [
'foreignKey' => 'hero_media_id',
'className' => 'Collections'
]);
查询的完整、简单版本,其中 returns 所有字段,包括关联的 table 字段 HeroMedia
和 IconMedia
。
$this->Collections->find()
->contain(['Participations', 'HeroMedia', 'IconMedia']);
生成
SELECT Collections.id AS `Collections__id`,
Collections.name AS `Collections__name`,
Collections.slug AS `Collections__slug`,
Collections.description AS `Collections__description`,
Collections.icon_media_id AS `Collections__icon_media_id`,
Collections.hero_media_id AS `Collections__hero_media_id`,
Collections.user_id AS `Collections__user_id`,
Collections.created AS `Collections__created`,
Collections.modified AS `Collections__modified`,
HeroMedia.id AS `HeroMedia__id`,
HeroMedia.file AS `HeroMedia__file`,
HeroMedia.description AS `HeroMedia__description`,
HeroMedia.caption AS `HeroMedia__caption`,
HeroMedia.source AS `HeroMedia__source`,
IconMedia.id AS `IconMedia__id`,
IconMedia.file AS `IconMedia__file`,
IconMedia.description AS `IconMedia__description`,
IconMedia.caption AS `IconMedia__caption`,
IconMedia.source AS `IconMedia__source`
FROM collections Collections
LEFT JOIN media HeroMedia ON HeroMedia.id = (Collections.hero_media_id)
LEFT JOIN media IconMedia ON IconMedia.id = (Collections.icon_media_id)
这正是我所期望的。但是,我想限制从 collection
table 返回的 selected 字段。我尝试了以下语句:
$this->Collections->find()
->select( [ 'id', 'name', 'slug', 'description', 'icon_media_id', 'hero_media_id' ] )
->contain(['Participations', 'HeroMedia', 'IconMedia']);
不幸的是,这会生成以下 SQL。请注意 JOIN
仍然存在,但是 IconMedia
和 HeroMedia 的 SELECT
已经消失。
SELECT Collections.id AS `Collections__id`,
Collections.name AS `Collections__name`,
Collections.slug AS `Collections__slug`,
Collections.description AS `Collections__description`,
Collections.icon_media_id AS `Collections__icon_media_id`,
Collections.hero_media_id AS `Collections__hero_media_id`
FROM collections Collections
LEFT JOIN media HeroMedia ON HeroMedia.id = (Collections.hero_media_id)
LEFT JOIN media IconMedia ON IconMedia.id = (Collections.icon_media_id)
也许虚拟 tables HeroMedia
和 IconMedia
有问题(不确定它们的正确 CakePHP 名称),但它们似乎可以正常工作没有 ->select
的简单 find()
。我试过通读 Query Builder and Associations 文档,但没有找到任何可以解释这种现象的内容。
您需要在所有字段上使用 Table::aliasField()。
->contain([
$this->aliasField('name'),
'OtherTable.field',
'YetAnotherTable.field'
]);
我有一个相当简单的查询,它针对包含的字段生成不同的 SQL 语句,具体取决于我是否将字段指定为 select。我知道这很令人困惑,所以我会尝试用代码来描述问题。
我设置了以下关联,它们在简单的 find()
上工作正常,但当我尝试使用 find()->select
时却不行。
集合表:
$this->belongsTo('IconMedia', [
'foreignKey' => 'icon_media_id',
'className' => 'Media'
]);
$this->belongsTo('HeroMedia', [
'foreignKey' => 'hero_media_id',
'className' => 'Media'
]);
媒体表:
$this->hasMany('CollectionsIconMedia', [
'foreignKey' => 'icon_media_id',
'className' => 'Collections'
]);
$this->hasMany('CollectionsHeroMedia', [
'foreignKey' => 'hero_media_id',
'className' => 'Collections'
]);
查询的完整、简单版本,其中 returns 所有字段,包括关联的 table 字段 HeroMedia
和 IconMedia
。
$this->Collections->find()
->contain(['Participations', 'HeroMedia', 'IconMedia']);
生成
SELECT Collections.id AS `Collections__id`,
Collections.name AS `Collections__name`,
Collections.slug AS `Collections__slug`,
Collections.description AS `Collections__description`,
Collections.icon_media_id AS `Collections__icon_media_id`,
Collections.hero_media_id AS `Collections__hero_media_id`,
Collections.user_id AS `Collections__user_id`,
Collections.created AS `Collections__created`,
Collections.modified AS `Collections__modified`,
HeroMedia.id AS `HeroMedia__id`,
HeroMedia.file AS `HeroMedia__file`,
HeroMedia.description AS `HeroMedia__description`,
HeroMedia.caption AS `HeroMedia__caption`,
HeroMedia.source AS `HeroMedia__source`,
IconMedia.id AS `IconMedia__id`,
IconMedia.file AS `IconMedia__file`,
IconMedia.description AS `IconMedia__description`,
IconMedia.caption AS `IconMedia__caption`,
IconMedia.source AS `IconMedia__source`
FROM collections Collections
LEFT JOIN media HeroMedia ON HeroMedia.id = (Collections.hero_media_id)
LEFT JOIN media IconMedia ON IconMedia.id = (Collections.icon_media_id)
这正是我所期望的。但是,我想限制从 collection
table 返回的 selected 字段。我尝试了以下语句:
$this->Collections->find()
->select( [ 'id', 'name', 'slug', 'description', 'icon_media_id', 'hero_media_id' ] )
->contain(['Participations', 'HeroMedia', 'IconMedia']);
不幸的是,这会生成以下 SQL。请注意 JOIN
仍然存在,但是 IconMedia
和 HeroMedia 的 SELECT
已经消失。
SELECT Collections.id AS `Collections__id`,
Collections.name AS `Collections__name`,
Collections.slug AS `Collections__slug`,
Collections.description AS `Collections__description`,
Collections.icon_media_id AS `Collections__icon_media_id`,
Collections.hero_media_id AS `Collections__hero_media_id`
FROM collections Collections
LEFT JOIN media HeroMedia ON HeroMedia.id = (Collections.hero_media_id)
LEFT JOIN media IconMedia ON IconMedia.id = (Collections.icon_media_id)
也许虚拟 tables HeroMedia
和 IconMedia
有问题(不确定它们的正确 CakePHP 名称),但它们似乎可以正常工作没有 ->select
的简单 find()
。我试过通读 Query Builder and Associations 文档,但没有找到任何可以解释这种现象的内容。
您需要在所有字段上使用 Table::aliasField()。
->contain([
$this->aliasField('name'),
'OtherTable.field',
'YetAnotherTable.field'
]);