Laravel中基于职位层级构建指定员工的父子树形数组
基于职位父子关系生成员工树形结构的解决方案
问题背景
拥有员工(Pegawai)和职位(Jabatan)两个数据库表,结构如下:
员工表(Pegawai)
id | name | id_jabatan 1 | Bee | 1 2 | Caa | 2 3 | Duu | 3 4 | Sue | 3 5 | Goo | 2
职位表(Jabatan)
id | id_parent | jabatan_nama 1 | 0 | manager 2 | 1 | leader 3 | 2 | staff
需要生成指定员工的树形结构,期望输出如下:
"parent" => { "id": "1", "nama": "Bee", "jabatan": { "id": "1", "jabatan_nama": "Manager" } } "child" => [ { "id": "2", "nama": "Caa", "jabatan": { "id": "2", "jabatan_nama": "leader" }, "child" => [ { "id": "3", "nama": "Duu", "jabatan": { "id": "3", "jabatan_nama": "staff" } }, { "id": "4", "nama": "Sue", "jabatan": { "id": "3", "jabatan_nama": "staff" } } ] }, { "id": "5", "nama": "Goo", "jabatan": { "id": "2", "jabatan_nama": "leader" }, "child" => [ { "id": "3", "nama": "Duu", "jabatan": { "id": "3", "jabatan_nama": "staff" } }, { "id": "4", "nama": "Sue", "jabatan": { "id": "3", "jabatan_nama": "staff" } } ] } ]
现有递归代码只能获取一级子员工,无法获取深层子节点,代码如下:
public function __invoke($_, array $args) { $pegawai = Pegawai::find($args['pegawaiId']); $jabatanDibawah = Jabatan::where("id_parent", "=", $pegawai->id_jabatan)->get(); $hirarki = $this->getPegawaiTree($jabatanDibawah); return [ "parent" => $pegawai, "child" => $hirarki ]; } function getPegawaiTree($jabatanDibawah) { $hirarki = []; foreach ($jabatanDibawah as $jabatan) { $pegawaiBawah = Pegawai::select('id','nama','id_jabatan')->where("id_jabatan", "=", $jabatan->id)->first(); if ($pegawaiBawah) { $hirarki[] = $pegawaiBawah; $jabatanBawah = Jabatan::where("id_parent", "=", $pegawaiBawah->id_jabatan)->get(); if ($jabatanBawah) { $this->getPegawaiTree($jabatanBawah); } } } return $hirarki; }
补充说明:需生成指定员工的树形结构,不能查询所有员工;顶级职位父级值为null。
解决方案
原代码存在三个核心问题:
- 递归调用时未将返回的子节点赋值给当前员工的
child属性 - 获取同职位员工时用了
first(),导致仅获取到第一个员工,遗漏同职位的其他员工 - 未将职位信息关联到员工数据中
修改后的完整代码如下:
public function __invoke($_, array $args) { // 获取指定员工并关联职位信息 $pegawai = Pegawai::with('jabatan')->find($args['pegawaiId']); // 处理顶级职位父级为null的情况 if ($pegawai->jabatan->id_parent == 0) { $pegawai->jabatan->id_parent = null; } // 获取当前员工职位的子职位 $jabatanDibawah = Jabatan::where("id_parent", "=", $pegawai->jabatan->id)->get(); $hirarki = $this->getPegawaiTree($jabatanDibawah); return [ "parent" => $pegawai->toArray(), "child" => $hirarki ]; } function getPegawaiTree($jabatanDibawah) { $hirarki = []; foreach ($jabatanDibawah as $jabatan) { // 获取当前职位下的所有员工,关联职位信息 $pegawaiBawahList = Pegawai::with('jabatan') ->select('id','nama','id_jabatan') ->where("id_jabatan", "=", $jabatan->id) ->get() ->toArray(); foreach ($pegawaiBawahList as $pegawaiBawah) { // 获取当前员工职位的子职位 $jabatanBawah = Jabatan::where("id_parent", "=", $jabatan->id)->get(); if ($jabatanBawah->isNotEmpty()) { // 递归获取子节点并赋值给child属性 $pegawaiBawah['child'] = $this->getPegawaiTree($jabatanBawah); } $hirarki[] = $pegawaiBawah; } } return $hirarki; }
关键修改点说明
- 关联职位信息:使用
with('jabatan')预加载职位关联,确保员工数据包含完整的职位信息 - 处理同职位多员工:将
first()改为get(),遍历所有同职位员工,避免遗漏 - 递归结果赋值:将递归调用
getPegawaiTree()的返回值赋值给当前员工的child字段,完成树形结构的嵌套 - 顶级职位处理:判断职位父级为0时转为
null,符合需求
内容的提问来源于stack exchange,提问作者Laggio Vanotto
相关产品推荐
相关产品推荐

