Yii2中ActiveDataProvider无法获取关联Theme的name值问题
Yii2中通过ActiveDataProvider获取关联模型Theme的name值问题
模型关联定义
Report 模型
public function getCampaign(): \yii\db\ActiveQuery { return $this->hasOne(Campaign::class, ['cid' => 'cid']); }
Campaign 模型
public function getStream() { return $this->hasOne(Stream::class, ['id' => 'stream_id']); }
Stream 模型
public function getTheme(): \yii\db\ActiveQuery { return $this->hasOne(Theme::class, ['id' => 'theme_id']); }
查询代码
$query = new Report(); $query = $query->find()->select($columns_array); $query->joinWith('campaign.stream.theme t'); $query->groupBy('t.name');
问题现象
- 执行
dd($dataProvider->getModels());查看结果时,无法获取到Theme的name值 - 但通过
dd($query->prepare(\Yii::$app->db->queryBuilder)->createCommand()->rawSql);查看生成的SQL语句,能正确查询到Theme的name值,生成的SQL如下:
SELECT "t"."name", sum(total_cost) AS "total_cost", sum(real_app_install) AS "real_app_install", sum(real_result_conversion) AS "real_result_conversion", sum(click) AS "click", sum(impression) AS "impression", sum(af_subs) AS "af_subs", sum(af_revenue) AS "af_revenue", avg(ctr) AS "ctr", avg(cpc) AS "cpc", avg(cpm) AS "cpm" FROM "reports" LEFT JOIN "campaigns" ON "reports"."cid" = "campaigns"."cid" LEFT JOIN "streams" ON "campaigns"."stream_id" = "streams"."id" LEFT JOIN "themes" "t" ON "streams"."theme_id" = "t"."id" GROUP BY "t"."name"
解决方案
问题根源是Yii2的ActiveRecord会自动把查询结果映射到Report模型的属性上,但t.name并没有对应到Report模型的字段,且分组查询的特性会导致嵌套关联模型无法自动填充。可以通过以下几种方式解决:
方法1:给Report模型添加虚拟属性
在Report模型中定义一个虚拟属性,查询时将t.name别名映射到该属性:
// Report.php 中添加属性 public $theme_name; // 修改查询代码的select部分 $columns_array[] = 't.name AS theme_name'; $query = Report::find()->select($columns_array); $query->joinWith('campaign.stream.theme t'); $query->groupBy('t.name');
之后就能通过 $model->theme_name 获取到Theme的name值。
方法2:将查询结果转为数组格式
设置ActiveDataProvider的asArray为true,让查询结果以数组形式返回,直接从数组中取name值:
$dataProvider = new ActiveDataProvider([ 'query' => $query, 'asArray' => true, ]);
此时$dataProvider->getModels()返回数组,可通过$item['name']直接获取值。
方法3:预加载关联(分组场景不推荐)
如果分组逻辑允许,可尝试用with()预加载关联,但分组后每个Report对应的关联数据可能不唯一,这种方法更适合普通列表查询,分组场景下容易出现数据不匹配的问题:
$query->with('campaign.stream.theme');
内容的提问来源于stack exchange,提问作者FeR-S
相关产品推荐
相关产品推荐

