CakePHP 3 Query Builder缺失时指定选择字段时包含字段

时间:2017-08-29 20:41:51

标签: cakephp cakephp-3.0

我有一个相当简单的查询,根据是否指定要选择的字段,根据包含的字段生成不同的SQL语句。我知道这很混乱,所以我会尝试用代码描述问题。

我设置了以下关联,它们可以使用简单的find()正常工作,但在我尝试使用find()->select时却无法正常工作。

CollectionsTable:

    $this->belongsTo('IconMedia', [
        'foreignKey' => 'icon_media_id',
        'className' => 'Media'
    ]);
    $this->belongsTo('HeroMedia', [
        'foreignKey' => 'hero_media_id',
        'className' => 'Media'
    ]);

MediaTable:

    $this->hasMany('CollectionsIconMedia', [
        'foreignKey' => 'icon_media_id',
        'className' => 'Collections'
    ]);
    $this->hasMany('CollectionsHeroMedia', [
        'foreignKey' => 'hero_media_id',
        'className' => 'Collections'
    ]);

查询的完整简单版本,它返回所有字段,包括关联表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表返回的选定字段。我尝试了以下声明:

$this->Collections->find()
        ->select( [ 'id', 'name', 'slug', 'description', 'icon_media_id', 'hero_media_id' ] )
        ->contain(['Participations', 'HeroMedia', 'IconMedia']);

遗憾的是,这会生成以下SQL。请注意,JOIN仍然存在,但SELECT和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` 
     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)

可能虚拟表HeroMediaIconMedia存在问题(不确定它们的CakePHP名称是否正确),但它们似乎适用于简单的find()而没有->select。我试过阅读Query BuilderAssociations文档,但没有找到任何解释这种现象的内容。

1 个答案:

答案 0 :(得分:1)

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

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