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 字段 HeroMediaIconMedia

$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 HeroMediaIconMedia 有问题(不确定它们的正确 CakePHP 名称),但它们似乎可以正常工作没有 ->select 的简单 find()。我试过通读 Query Builder and Associations 文档,但没有找到任何可以解释这种现象的内容。

您需要在所有字段上使用 Table::aliasField()

->contain([
    $this->aliasField('name'),
    'OtherTable.field',
    'YetAnotherTable.field'
]);