$item) { if ($item[$pidField] == 0) { $tree[] = &$items[$id]; } else { if (isset($items[$item[$pidField]])) { $items[$id]['level'] = $items[$item[$pidField]]['level'] + 1; if (!isset($items[$item[$pidField]]['children'])) { $items[$item[$pidField]]['children'] = []; } $items[$item[$pidField]]['children'][] = &$items[$id]; } } } return $tree; } /** * 将树形结构扁平化为列表(带层级前缀) * * @param array $tree 树形结构数据 * @param string $prefix 前缀字符 * @param string $field 显示字段名 * @param int $level 层级 * @return array */ public static function flattenWithPrefix(array $tree, string $prefix = '--', string $field = 'name', int $level = 0): array { $result = []; foreach ($tree as $item) { $item[$field . '_with_prefix'] = str_repeat($prefix, $item['level']) . $item[$field]; $result[] = $item; if (isset($item['children']) && !empty($item['children'])) { $children = static::flattenWithPrefix($item['children'], $prefix, $field, $item['level'] + 1); $result = array_merge($result, $children); } } return $result; } /** * 根据父ID查找所有子节点(包括子孙节点) * * @param array $data 数据列表 * @param int $parentId 父级ID * @param string $pidField 父级字段名 * @param string $idField ID字段名 * @return array */ public static function findChildren(array $data, int $parentId, string $pidField = 'parent_id', string $idField = 'id'): array { $children = []; foreach ($data as $item) { if ($item[$pidField] == $parentId) { $children[] = $item; $grandChildren = static::findChildren($data, $item[$idField], $pidField, $idField); $children = array_merge($children, $grandChildren); } } return $children; } /** * 获取指定节点的所有父级节点 * * @param array $data 数据列表 * @param int $id 当前节点ID * @param string $pidField 父级字段名 * @param string $idField ID字段名 * @return array */ public static function getParents(array $data, int $id, string $pidField = 'parent_id', string $idField = 'id'): array { $parents = []; foreach ($data as $item) { if ($item[$idField] == $id) { if ($item[$pidField] != 0) { $parents[] = $item; $parentParents = static::getParents($data, $item[$pidField], $pidField, $idField); $parents = array_merge($parents, $parentParents); } break; } } return $parents; } /** * 获取指定节点的子孙节点ID列表 * * @param array $data 数据列表 * @param int $parentId 父级ID * @param string $pidField 父级字段名 * @param string $idField ID字段名 * @return array */ public static function getChildrenIds(array $data, int $parentId, string $pidField = 'parent_id', string $idField = 'id'): array { $ids = []; $children = static::findChildren($data, $parentId, $pidField, $idField); foreach ($children as $child) { $ids[] = $child[$idField]; } return $ids; } /** * 检查是否有子节点 * * @param array $data 数据列表 * @param int $parentId 父级ID * @param string $pidField 父级字段名 * @return bool */ public static function hasChildren(array $data, int $parentId, string $pidField = 'parent_id'): bool { foreach ($data as $item) { if ($item[$pidField] == $parentId) { return true; } } return false; } /** * 构建带有权限列表的资源树(权限不显示在树结构中) * * @param array $data 资源数据列表 * @param int $parentId 父级ID * @param string $pidField 父级字段名 * @param string $idField ID字段名 * @param string $typeField 类型字段名 * @param string $permissionType 权限类型标识 * @param int $level 当前层级 * @return array */ public static function buildWithAuthList( array $data, int $parentId = 0, string $pidField = 'parent_id', string $idField = 'id', string $typeField = 'type', string $permissionType = 'permission', int $level = 0 ): array { $tree = []; foreach ($data as $item) { // 只处理指定父级的非权限节点 if ($item[$pidField] == $parentId && $item[$typeField] != $permissionType) { $item['level'] = $level; // 递归处理子节点(非权限类型) $children = static::buildWithAuthList($data, $item[$idField], $pidField, $idField, $typeField, $permissionType, $level + 1); if (!empty($children)) { $item['children'] = $children; } // 收集当前节点下的所有权限 $item['auth_list'] = static::collectDirectPermissions($data, $item[$idField], $pidField, $typeField, $permissionType); $tree[] = $item; } } return $tree; } /** * 收集指定节点下的直接权限项(只收集直接子节点中的权限) * * @param array $data 数据列表 * @param int $parentId 父级ID * @param string $pidField 父级字段名 * @param string $typeField 类型字段名 * @param string $permissionType 权限类型标识 * @return array */ public static function collectDirectPermissions( array $data, int $parentId, string $pidField = 'parent_id', string $typeField = 'type', string $permissionType = 'permission' ): array { $permissions = []; foreach ($data as $item) { // 收集直接子节点中的权限类型 if ($item[$pidField] == $parentId && $item[$typeField] == $permissionType) { $permissions[] = $item; } } return $permissions; } /** * 使用引用方式构建带有权限列表的资源树(权限不显示在树结构中) * * @param array $data 资源数据列表 * @param string $pidField 父级字段名 * @param string $idField ID字段名 * @param string $typeField 类型字段名 * @param string $permissionType 权限类型标识 * @return array */ public static function buildWithAuthListAndReference( array $data, string $pidField = 'parent_id', string $idField = 'id', string $typeField = 'type', string $permissionType = 'permission' ): array { $items = []; $tree = []; // 建立以id为索引的数组(只包含非权限节点) foreach ($data as $item) { if ($item[$typeField] != $permissionType) { $item['level'] = 0; $items[$item[$idField]] = $item; } } // 构建树形结构 foreach ($items as $id => $item) { if ($item[$pidField] == 0) { $tree[] = &$items[$id]; } else { if (isset($items[$item[$pidField]])) { $items[$id]['level'] = $items[$item[$pidField]]['level'] + 1; if (!isset($items[$item[$pidField]]['children'])) { $items[$item[$pidField]]['children'] = []; } $items[$item[$pidField]]['children'][] = &$items[$id]; } } } // 为每个节点添加权限列表 foreach ($items as &$item) { $item['auth_list'] = static::collectDirectPermissions($data, $item[$idField], $pidField, $typeField, $permissionType); } return $tree; } }