> */ public function treeForUser(AdminUser $user): array { $menus = $this->menusQueryForUser($user); $tree = $this->buildTree($menus); return $tree->values()->all(); } protected function menusQueryForUser(AdminUser $user): Collection { $base = Menu::query()->where('status', 1)->orderBy('sort'); if ($user->isSuperAdmin()) { return $base->get(); } $roleIds = $user->roles()->where('status', 1)->pluck('id'); $menuIds = DB::table('role_menus') ->whereIn('role_id', $roleIds) ->pluck('menu_id') ->unique() ->all(); if ($menuIds === []) { return collect(); } $expandedIds = $this->expandMenuParents($menuIds); return $base->whereIn('id', $expandedIds)->get(); } /** * @param array $menuIds * @return array */ protected function expandMenuParents(array $menuIds): array { $idSet = collect($menuIds)->flip()->all(); $queue = $menuIds; while ($queue !== []) { $id = array_pop($queue); $m = Menu::query()->find($id); if ($m && $m->parent_id && ! isset($idSet[$m->parent_id])) { $idSet[$m->parent_id] = 0; $queue[] = $m->parent_id; } } return array_map('intval', array_keys($idSet)); } /** * @param Collection $menus * @return \Illuminate\Support\Collection> */ protected function buildTree(Collection $menus): Collection { $byParent = $menus->groupBy(fn (Menu $m) => $m->parent_id ?? 0); $build = function ($parentId) use (&$build, $byParent): Collection { return ($byParent->get($parentId, collect()))->map(function (Menu $m) use (&$build) { $node = [ 'id' => $m->id, 'parent_id' => $m->parent_id, 'path' => $m->path, 'name' => $m->name, 'title' => $m->title, 'component' => $m->component, 'icon' => $m->icon, 'sort' => $m->sort, 'visible' => $m->visible, 'keep_alive' => $m->keep_alive, 'permission_code' => $m->permission_code, 'status' => (int) $m->status, ]; $children = $build($m->id); if ($children->isNotEmpty()) { $node['children'] = $children->values()->all(); } return $node; }); }; return $build(0); } }