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

如何在Laravel中用Eloquent eager loading让关联查询返回字符串字段

Laravel Eloquent 关联字段扁平化输出方案

完全可以实现,以下两种是生产环境常用的优雅实现方式:


方案1:使用Eloquent访问器(最通用,无需修改查询逻辑)

适合大部分业务场景,自动处理序列化输出,不需要调整预加载逻辑:

  1. 给Product模型添加访问器,同时把自定义字段追加到序列化输出列表:
// app/Models/Product.php
class Product extends Model
{
    // 定义需要追加到JSON/数组输出的自定义属性
    protected $appends = ['product_tag'];

    // 保留原有关联定义
    public function ProductTag()
    {
        return $this->hasMany(ProductTag::class);
    }
    public function Category()
    {
        return $this->belongsTo(Category::class);
    }

    // 定义product_tag字段的访问器
    public function getProductTagAttribute()
    {
        // 直接从预加载的关联数据中拼接tag字符串,无数据返回空字符串
        return $this->ProductTag->pluck('tag')->join(',');
    }
}
  1. 查询时只需要正常预加载关联即可,不需要额外处理:
public static function list(){
    // 预加载关联避免N+1问题
    return Category::with(['Product.ProductTag'])->get();
}

该方案最终输出的product对象会直接携带product_tag字符串字段,完全符合预期格式。


方案2:查询时直接拼接字段(性能更高,适合大数量查询)

如果不需要保留原有的ProductTag关联数据输出,想要一次查询拿到结果,可以直接用join拼接字段:

public static function list(){
    return Category::with(['Product' => function($query){
        $query->selectRaw('products.*, GROUP_CONCAT(product_tags.tag) as product_tag')
              ->leftJoin('product_tags', 'products.id', '=', 'product_tags.product_id')
              ->groupBy('products.id');
    }])->get();
}

注意:如果你的MySQL开启了ONLY_FULL_GROUP_BY模式,需要把products表所有需要查询的字段都加到groupBy参数中,或者调整SQL模式适配。


原有写法问题说明

你之前定义的tag是hasMany类型关联,哪怕你调用first()方法,返回结果依然是模型实例或空集合,所以一定会嵌套一层数组/对象结构。访问器方案直接把计算后的值挂载到Product模型的顶层属性,就可以去掉多余的层级。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 18:33:02