
本文详解如何从 JSON 格式的工作日数据中提取 day_index,结合标准星期映射(周一=2…周日=1),生成覆盖全部 7 天的结构化日程数组,并正确处理“存在则标记为工作日、不存在则设为非工作日”的逻辑,同时修复 JSON 解析失败、循环逻辑错误等常见陷阱。
本文详解如何从 json 格式的工作日数据中提取 `day_index`,结合标准星期映射(周一=2…周日=1),生成覆盖全部 7 天的结构化日程数组,并正确处理“存在则标记为工作日、不存在则设为非工作日”的逻辑,同时修复 json 解析失败、循环逻辑错误等常见陷阱。
在 PHP 中构建完整的周工作日程时,一个典型需求是:以固定星期顺序(如 Sunday→Saturday)为基准,对每个日期索引(day_index)检查其是否存在于原始工作时间数据中;若存在,则标记 'working' => true 并保留原始信息;若不存在,则补全 'working' => false 及对应 day_index。但实际实现中常遇到两大核心问题:JSON 解析失败 和 嵌套循环逻辑错误 —— 这正是原代码输出异常的根本原因。
✅ 正确做法:分步解决关键问题
1. 首先验证并修复 JSON 解析
原代码中 $working_hours_arr 是字符串,但未检查 json_decode() 是否成功。PHP 中若 JSON 格式非法或编码异常(如 BOM、隐藏控制字符),json_decode() 会静默返回 null,而 json_last_error() 才能暴露真实错误:
$working_hours_arr = '[{"day_index":"2","start_time":"10:00:00","end_time":"19:00:00","break":[]},...]';
$decoded = json_decode($working_hours_arr, true);
if (json_last_error() !== JSON_ERROR_NONE) {
throw new RuntimeException('Invalid JSON: ' . json_last_error_msg());
}
// $decoded 现在是关联数组,安全可用⚠️ 注意:必须使用
true参数(即json_decode($str, true))获取关联数组,否则返回对象,后续用$obj->day_index会因类型不一致导致逻辑失效。
2. 重构循环逻辑:避免内层覆盖
原代码中双重 foreach 导致严重逻辑缺陷:
- 对每个
$day(如'Monday'=>2),都会遍历全部$decoded元素; - 若某天索引(如
2)匹配第一个元素 → 设为['working'=>true]; - 但紧接着匹配失败的其他元素(如
3,4,5)会反复执行else分支,最终将该$day覆盖为['working'=>false]; - 结果所有天均被设为
false。
✅ 正确方式:先预存已存在的 day_index 集合,再单次遍历 $days 判断是否存在:
// Step 1: 提取所有有效 day_index 到查找集合(提高效率)
$availableIndices = [];
foreach ($decoded as $item) {
$idx = (int)$item['day_index'];
if ($idx >= 1 && $idx <= 7) {
$availableIndices[$idx] = true;
}
}
// Step 2: 按标准星期顺序构建完整 schedule
$days = [
'Sunday' => 1,
'Monday' => 2,
'Tuesday' => 3,
'Wednesday' => 4,
'Thursday' => 5,
'Friday' => 6,
'Saturday' => 7,
];
$schedule = [];
foreach ($days as $dayName => $index) {
$schedule[$dayName] = [
'day_index' => $index,
'working' => isset($availableIndices[$index])
];
}
print_r($schedule);3. 进阶:合并原始工作时间数据(可选)
若需在 working => true 的条目中保留 start_time、end_time 等字段,可增强逻辑:
// 构建索引到原始数据的映射
$hoursMap = [];
foreach ($decoded as $item) {
$idx = (int)$item['day_index'];
if ($idx >= 1 && $idx <= 7) {
$hoursMap[$idx] = $item;
}
}
// 构建 schedule(含详情)
foreach ($days as $dayName => $index) {
if (isset($hoursMap[$index])) {
$schedule[$dayName] = array_merge(
['day_index' => $index, 'working' => true],
$hoursMap[$index]
);
} else {
$schedule[$dayName] = [
'day_index' => $index,
'working' => false
];
}
}? 总结与最佳实践
-
永远校验
json_decode()结果:用json_last_error()+json_last_error_msg()定位解析失败原因; -
避免“边遍历边覆盖”的嵌套循环:优先构建查找表(如
isset($map[$key])),再单次生成目标结构; -
明确数据类型:
json_decode($str, true)返回数组更利于 PHP 数组操作; -
防御性编程:对
day_index做范围校验(1–7),防止脏数据干扰逻辑; -
语义清晰命名:如
$availableIndices比$obj更易理解其用途。
通过以上修正,你将得到一个结构统一、逻辑健壮、可直接用于前端渲染或 API 响应的完整周工作日程数组。

















