You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2关联查询product_url与shop表时ActiveRecord丢失tag字段问题

字段丢失原因
  1. ActiveRecord(以下简称AR)对象在填充属性时,只会识别当前模型对应数据表的原生字段,以及模型显式声明的自定义属性。你通过JOIN查询带出的shop表tag字段不属于product_url表原生字段,也没有在ProductUrl模型中做显式声明,所以AR对象会自动过滤该字段。而asArray()返回数组时不会做模型属性合法性校验,会直接返回查询得到的所有字段,因此可以正常拿到tag。
  2. 如果你是通过with()预加载shop关联,但直接尝试从ProductUrl对象上取tag属性也会失败:tag属于关联的Shop模型的属性,默认保存在ProductUrl对象的shop关联属性中,不会直接挂载到ProductUrl的一级属性上。
解决方案

方案1:通过关联属性访问(推荐)

只要getShop()关联方法的匹配逻辑正确,查询时预加载关联后,直接从关联对象上取tag即可,不需要额外修改模型字段声明:

// ProductUrl模型中关联方法示例,注意匹配域名的逻辑写在onCondition中
public function getShop()
{
    return $this->hasOne(Shop::class, [])
        ->onCondition('SUBSTRING_INDEX(shop.url, "/", 3) = SUBSTRING_INDEX(product_url.url, "/", 3)');
}

// 查询代码
$productUrls = ProductUrl::find()
    ->with('shop')
    ->all();

// 访问tag字段
foreach ($productUrls as $item) {
    $tag = $item->shop->tag;
}

方案2:在ProductUrl模型中声明tag属性

如果你需要直接在ProductUrl对象的一级属性上访问tag,可以手动声明该属性,查询时显式指定查询shop.tag字段:

// 在ProductUrl类中新增公共属性
public $tag;

// 查询代码
$productUrls = ProductUrl::find()
    ->select(['product_url.*', 'shop.tag'])
    ->leftJoin('shop', 'SUBSTRING_INDEX(shop.url, "/", 3) = SUBSTRING_INDEX(product_url.url, "/", 3)')
    ->all();

// 直接访问tag
$tag = $productUrls[0]->tag;

方案3:重写attributes方法声明额外字段

不想新增公共属性的话,也可以重写ProductUrl的attributes()方法,把tag加入可识别的属性列表,效果和方案2一致:

public function attributes()
{
    return array_merge(parent::attributes(), ['tag']);
}

内容的提问来源于stack exchange,提问作者user2285323

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 15:06:03