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

Laravel多对多关联重复问题:如何将pivot表role_id聚合为数组

Laravel多对多关联聚合pivot角色ID解决方案

你可以选择以下两种方案实现需求:

方案1:集合后置处理(实现最简单,适合中小数据量)

不需要修改原有关联定义,在查询出结果后通过Laravel集合方法分组聚合即可:

// 查询指定作者的作品并处理
$author = Author::find($yourAuthorId);
$writings = $author->writings
    // 按作品ID分组
    ->groupBy('id')
    ->map(function ($itemGroup) {
        // 取第一个作品作为基础数据
        $writing = $itemGroup->first();
        // 聚合该作品下所有角色ID
        $writing->pivot->role_id = $itemGroup->pluck('pivot.role_id')->unique()->values()->toArray();
        return $writing;
    })
    // 重置集合索引
    ->values();

返回的$writings就已经是每个作品仅一条、pivot的role_id为数组的结构,直接序列化输出即可得到你想要的JSON格式。

方案2:查询层聚合(性能更优,适合大数据量场景)

直接在关联查询时通过SQL聚合函数合并角色ID,减少查询返回的数据量:

第一步:修改关联定义

public function writings(){
    return $this->belongsToMany(Writing::class, 'author_writing', 'author_id', 'writing_id')
        ->selectRaw('writings.*, GROUP_CONCAT(author_writing.role_id) as aggregate_role_ids')
        // 按作品ID分组去重
        ->groupBy('writings.id')
        ->withPivot(['writing_id', 'author_id']);
}

注:如果使用PostgreSQL数据库,将GROUP_CONCAT替换为STRING_AGG(author_writing.role_id, ',')即可。

第二步:格式化输出

$author = Author::find($yourAuthorId);
$writings = $author->writings->map(function ($writing) {
    // 将聚合的字符串拆分为数组
    $writing->pivot->role_id = explode(',', $writing->aggregate_role_ids);
    // 清理临时聚合字段
    unset($writing->aggregate_role_ids);
    return $writing;
});

可选优化:API资源类统一格式化

如果是接口返回场景,你可以创建Laravel资源类统一处理输出结构,避免每次查询都重复写处理逻辑。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.18 00:06:03