如何将ScheduleController返回数组适配DateTimePicker的disabledTimeIntervals
如何将PHP返回的时间数组转换为Bootstrap DateTimePicker的disabledTimeIntervals格式
我有一个ScheduleController,从schedules表中获取start_time和end_time,代码如下:
$schedules = Schedule::select('start_time', 'end_time') ->where('weekday', $request->input('weekday')) ->get() ->toArray(); $collection = collect($schedules)->map(function ($time) { return [date("g:i", strtotime($time['start_time'])), date("g:i", strtotime($time['end_time']))]; })->flatten(); $data = $collection->values()->all(); // $data 输出格式类似: // ['6:30', '7:30'], // ['11:30', '12:30']
需要将上述格式转换为Bootstrap DateTimePicker的disabledTimeIntervals要求的格式,示例如下:
// 目标格式 disabledTimeIntervals: [ [ moment({ hour: 6, minute: 30 }), moment({ hour: 7, minute: 30 }) ], [ moment({ hour: 11, minute: 30 }), moment({ hour: 12, minute: 30 }) ] ],
已尝试的方案及问题
1. JavaScript处理方案(多数组失效)
尝试用moment转换时间,但传入多数组时无法禁用对应时间,单数组正常:
const stringToDate = (dateString) => { const [hours, minutes] = dateString.split(':'); return moment().hours(hours).minutes(minutes); } const formatDates = datesToFormat => datesToFormat.map(dateString => { if (Array.isArray(dateString)) { return dateString.map(s => stringToDate(s)); } else { return stringToDate(dateString); } }) let customOptions = { format: 'hh:mm A', disabledTimeIntervals: [ // 多数组时失效 formatDates([ ['6:30', '7:30'], ['11:30', '12:30'] ]) // 单数组(不嵌套外层[])时正常 // formatDates(['6:30', '7:30']) ], } $('.timepicker').datetimepicker(customOptions)
控制台输出显示格式不符合预期。
2. PHP处理方案(无法移除引号和多余逗号)
尝试用PHP直接生成目标格式,但结果存在引号和末尾多余逗号:
$user = User::find(1); $schedules = Schedule::select('start_time', 'end_time') ->whereBelongsTo($user) ->where('weekday', 1) ->get() ->toArray(); $collection = collect($schedules)->map(function ($time) { return [date("g:i", strtotime($time['start_time'])), date("g:i", strtotime($time['end_time']))]; }); $data = $collection->values()->all(); // $data 输出: // [ // [ // "6:45", // "7:45", // ], // [ // "10:30", // "11:30", // ], // ] $carrier = []; foreach ($data as $key => $a) { $detail1 = preg_split('/:/i', $a[0]); $detail2 = preg_split('/:/i', $a[1]); array_push($carrier, array(str_replace('"', "", 'moment({ hour:'.$detail1[0].', minute:'.$detail1[1].' }), moment({ hour:'.$detail2[0].', minute:'.$detail2[1].' })'))); } return $carrier;
当前输出结果:
[ [ "moment({ hour:6, minute:45 }), moment({ hour:7, minute:45 })", ], [ "moment({ hour:10, minute:30 }), moment({ hour:11, minute:30 })", ], ]
需要去掉引号和末尾多余逗号,得到目标格式。
解决方案
方案一:修正JavaScript处理逻辑
问题出在disabledTimeIntervals的结构上,原代码将处理后的二维数组又嵌套了一层[],导致变成三维数组。修改后直接将处理后的二维数组赋值给disabledTimeIntervals:
const stringToDate = (dateString) => { const [hours, minutes] = dateString.split(':'); return moment().hours(hours).minutes(minutes); } // 专门处理时间区间数组,返回符合要求的二维moment数组 const formatDisabledIntervals = (intervals) => { return intervals.map(intervalPair => { return intervalPair.map(timeStr => stringToDate(timeStr)); }); } // 在Blade中直接将PHP数组转为JSON const disabledTimePairs = {{ json_encode($data) }}; let customOptions = { format: 'hh:mm A', disabledTimeIntervals: formatDisabledIntervals(disabledTimePairs) } $('.timepicker').datetimepicker(customOptions);
方案二:PHP直接生成符合要求的JS代码字符串
通过PHP解析时间为小时和分钟,直接生成对应的moment代码片段,再在Blade中输出:
$user = User::find(1); $schedules = Schedule::select('start_time', 'end_time') ->whereBelongsTo($user) ->where('weekday', 1) ->get(); // 生成每个时间区间的moment字符串 $disabledIntervalStrings = $schedules->map(function ($schedule) { // 解析start_time的小时和分钟 $startParsed = date_parse_from_format('H:i:s', $schedule->start_time); // 解析end_time的小时和分钟 $endParsed = date_parse_from_format('H:i:s', $schedule->end_time); return "[moment({ hour: {$startParsed['hour']}, minute: {$startParsed['minute']} }), moment({ hour: {$endParsed['hour']}, minute: {$endParsed['minute']} })]"; })->implode(',');
在Blade模板中使用:
<script> let customOptions = { format: 'hh:mm A', disabledTimeIntervals: [<?= $disabledIntervalStrings ?>] } $('.timepicker').datetimepicker(customOptions); </script>
内容的提问来源于stack exchange,提问作者Lucky Person
相关产品推荐
相关产品推荐

