Laravel Eloquent按HasMany关联分组:按职位聚合用户ID
Laravel Eloquent按职位分组用户ID的实现方案
嘿,刚好我之前处理过类似需求,给你两种Laravel Eloquent的实现方式,都能精准输出你想要的键值对格式:
方法一:直接从UserPosition模型查询(性能更优)
这种方式不需要加载完整的User模型实例,仅操作关联表,查询效率更高,推荐优先使用:
use Illuminate\Support\Facades\DB; use App\Models\UserPosition; $groupedPositions = UserPosition::query() ->select('position', DB::raw('GROUP_CONCAT(user_id SEPARATOR ",") as user_ids')) ->groupBy('position') ->get() ->mapWithKeys(function ($entry) { return [$entry->position => explode(',', $entry->user_ids)]; });
逻辑说明:
- 用
GROUP_CONCAT聚合函数,把同一职位下的所有user_id拼接成逗号分隔的字符串; - 通过
mapWithKeys集合方法,将查询结果转换为「职位名 => 用户ID数组」的结构。
方法二:通过User模型关联查询
如果你的业务场景需要同时用到User模型的其他字段,可以从用户端发起查询:
use App\Models\User; $groupedPositions = User::with('positions') ->get() // 把每个用户的职位拆分为独立的「职位-用户ID」条目 ->flatMap(function ($user) { return $user->positions->map(function ($position) use ($user) { return [ 'position' => $position->position, 'user_id' => $user->id ]; }); }) // 按职位名称分组 ->groupBy('position') // 提取每组的用户ID并转为数组 ->map(function ($group) { return $group->pluck('user_id')->toArray(); });
逻辑说明:
- 先预加载所有用户的职位关联数据(避免N+1查询);
- 用
flatMap将嵌套的职位数据展开为一维集合; - 按职位分组后,提取每组的用户ID并转换为数组。
两种方法最终都会输出你需要的格式:
[ 'Developer' => [1, 9], 'Designer' => [2], 'Teacher' => [1], 'Singer' => [3, 10], 'Architect' => [3], 'Accountant' => [4, 11], 'Baker' => [2], 'Actress' => [7], 'Chef' => [11], 'Butcher' => [10, 8], 'Carpenter' => [8, 7, 1] ]
内容的提问来源于stack exchange,提问作者Andreas Hunter
相关产品推荐
相关产品推荐

