Laravel中REST API一维数组转树形及Carbon日期格式处理求助
Laravel 一维数组转树形结构+日期转换解决方案
一、SQL Server 日期转 Carbon 格式
两种简单实现方式,按需选择:
模型自动转换(推荐)
在对应数据模型中通过$casts属性指定日期字段类型,Laravel 会自动将 SQL Server 返回的日期转为 Carbon 实例:
class YourModel extends Model { protected $casts = [ 'created_at' => 'datetime', 'updated_at' => 'datetime', 'custom_date_column' => 'datetime', // 替换为你的日期字段名 ]; }
手动转换(直接查询时用)
如果是通过 DB 门面直接查询,可手动遍历转换:
$rawData = DB::table('your_table')->get(); $processedData = $rawData->map(function ($item) { $item->custom_date_column = \Carbon\Carbon::parse($item->custom_date_column); // 其他日期字段同理处理 return $item; });
二、一维数组转树形结构(最多4级)
假设你的一维数据中,每个节点包含Initials(节点标识)和parent_initials(父节点标识)两个核心关联字段,以下提供两种实现方案:
方案1:迭代式构建(直观易调试)
适合固定最多4级的场景,避免递归深度问题:
// 1. 先将数据按 Initials 分组,方便快速查找 $itemsMap = $processedData->keyBy('Initials'); // 2. 初始化树形结构,根节点为 Initials=NF 的数据 $tree = []; $rootNode = $itemsMap->get('NF'); if ($rootNode) { $rootNode['children'] = []; // 3. 构建第2级子节点(根节点的直接子节点) $level2Nodes = $itemsMap->filter(fn($item) => $item->parent_initials === 'NF'); foreach ($level2Nodes as $node2) { $node2['children'] = []; // NR 节点不需要子节点,跳过后续层级 if ($node2->Initials === 'NR') { $rootNode['children'][] = $node2; continue; } // 4. 构建第3级孙节点 $level3Nodes = $itemsMap->filter(fn($item) => $item->parent_initials === $node2->Initials); foreach ($level3Nodes as $node3) { $node3['children'] = []; if ($node3->Initials === 'NR') { $node2['children'][] = $node3; continue; } // 5. 构建第4级曾孙节点(最多到这一级) $level4Nodes = $itemsMap->filter(fn($item) => $item->parent_initials === $node3->Initials); foreach ($level4Nodes as $node4) { $node3['children'][] = $node4; } $node2['children'][] = $node3; } $rootNode['children'][] = $node2; } $tree[] = $rootNode; } return response()->json($tree);
方案2:递归式构建(代码更简洁)
适合层级逻辑灵活的场景,通过递归控制最大层级:
// 先完成日期转换和数据分组 $itemsMap = $processedData->keyBy('Initials'); // 递归构建子节点的函数 function buildChildNodes($parentInitials, $currentLevel, $maxLevel, $itemsMap) { // 超过最大层级或当前是NR节点,返回空数组 if ($currentLevel >= $maxLevel || $parentInitials === 'NR') { return []; } // 筛选当前父节点的子节点 $childNodes = $itemsMap->filter(fn($item) => $item->parent_initials === $parentInitials)->values(); // 递归处理子节点的子节点 return $childNodes->map(function ($node) use ($currentLevel, $maxLevel, $itemsMap) { $node['children'] = buildChildNodes($node->Initials, $currentLevel + 1, $maxLevel, $itemsMap); return $node; })->toArray(); } // 构建最终树形结构 $tree = []; $rootNode = $itemsMap->get('NF'); if ($rootNode) { $rootNode['children'] = buildChildNodes($rootNode->Initials, 1, 4, $itemsMap); $tree[] = $rootNode; } return response()->json($tree);
三、常见问题排查
- 父子关联错误:如果你的数据不是用
parent_initials关联父子,需替换代码中对应的关联字段名(比如parent_id)。 - 日期转换失败:若 SQL Server 返回的日期格式特殊,可指定格式解析,例如
Carbon::createFromFormat('Y-m-d H:i:s', $item->custom_date_column)。 - 层级嵌套异常:检查过滤条件是否匹配,确保子节点的父标识与父节点的
Initials完全一致(注意大小写)。
内容的提问来源于stack exchange,提问作者FaredCesar
相关产品推荐
相关产品推荐

