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

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。

解决方案

原代码存在三个核心问题:

  1. 递归调用时未将返回的子节点赋值给当前员工的child属性
  2. 获取同职位员工时用了first(),导致仅获取到第一个员工,遗漏同职位的其他员工
  3. 未将职位信息关联到员工数据中

修改后的完整代码如下:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 02:50:33