CodeIgniter Datetime Picker筛选报format()调用bool类型错误
报错根因
抛出Exception: Call to a member function format() on bool的直接原因是代码对DateTime::createFromFormat()的返回值未做校验:该方法解析失败时会返回布尔值false,后续直接在返回值上调用format()方法就会触发致命错误。
具体触发逻辑对应你代码里的三个问题:
- 控制器调用参数错误:你的数据库字段是
DATETIME类型,前端Datetime Picker传的是带时间的字符串,但你调用to_sql_date()处理自定义查询范围的起止日期时,没有传入第二个参数$datetime = true,代码默认走纯日期解析分支。 - 纯日期分支的解析逻辑不兼容带时间的输入:纯日期分支先用正则
/^(\d{4})-(\d{1,2})-(\d{1,2})$/校验输入,带时间的字符串(比如2024-05-20 16:30、05/20/2024 2:30 PM)无法匹配该正则,后续代码拿仅配置了纯日期规则的$from_format去解析带时间的完整字符串,格式不匹配导致DateTime::createFromFormat()解析失败返回false,最终触发报错。 - 传入不带时间的纯日期字符串时,要么能被正则直接匹配返回,要么和
$from_format的纯日期规则匹配可以解析成功,所以功能运行正常。
可行修复方案
按以下步骤修改代码即可解决问题,同时补上容错逻辑避免后续同类报错:
- 修正控制器的函数调用参数
找到get_where_report_period方法里自定义日期分支的两行调用,传入第二个参数开启datetime解析模式,同时优化范围查询逻辑避免漏数据,修改后代码如下:
} elseif ($months_report == 'custom') { // 第二个参数传true,走带时间的解析逻辑 $from_date = to_sql_date($this->input->post('report_from'), true); $to_date = to_sql_date($this->input->post('report_to'), true); // 范围查询优化:如果结束时间解析后是当天00:00:00,自动调整为当天23:59:59,避免漏掉当天的带时间数据 if ($to_date && date('H:i:s', strtotime($to_date)) == '00:00:00') { $to_date = date('Y-m-d 23:59:59', strtotime($to_date)); } if ($from_date == $to_date) { $custom_date_select = 'AND ' . $field . ' = "' . $this->db->escape_str($from_date) . '"'; } else { $custom_date_select = 'AND (' . $field . ' BETWEEN "' . $this->db->escape_str($from_date) . '" AND "' . $this->db->escape_str($to_date) . '")'; } }
- 给
to_sql_date函数的纯日期分支加解析容错
找到$datetime == false分支里直接调用createFromFormat()->format()的代码段,替换为带校验和兼容逻辑的版本,避免解析失败直接报错:
// 原代码直接调用format的部分替换为以下内容 $dateObj = DateTime::createFromFormat($from_format, $date); // 兼容意外传入带时间的字符串,自动截断取日期部分解析 if (!$dateObj && strpos($date, ' ') !== false) { $datePart = explode(' ', $date)[0]; $dateObj = DateTime::createFromFormat($from_format, $datePart); } // 兜底解析:如果指定格式解析失败,用strtotime兼容常见日期格式 if (!$dateObj) { $parsedTs = strtotime($date); if ($parsedTs) { return hooks()->apply_filters('to_sql_date_formatted', date('Y-m-d', $parsedTs)); } return null; } return hooks()->apply_filters( 'to_sql_date_formatted', $dateObj->format($to_date) );
- 给datetime分支加解析容错
找到$datetime == true分支最后生成格式化时间的代码段,替换为带校验的版本:
// 原代码 $d = date('Y-m-d H:i:s', strtotime($date)); 替换为以下内容 $parsedTs = strtotime($date); if (!$parsedTs) { $dateObj = DateTime::createFromFormat($from_format . ' H:i:s', $date); if (!$dateObj) { return null; } $d = $dateObj->format('Y-m-d H:i:s'); } else { $d = date('Y-m-d H:i:s', $parsedTs); }
额外注意项
确认前端Datetime Picker输出的日期格式和后端get_current_date_format(true)返回的系统配置日期格式一致,避免因前后端格式不匹配导致解析异常。
内容的提问来源于stack exchange,提问作者Carlvic Lim
相关产品推荐
相关产品推荐

