Laravel日期字段输入非法文本存1970-01-01,如何正确校验并提示错误?
问题根源
- 逻辑顺序错误:你提前在控制器把用户输入转成Y-m-d格式后才执行校验,
strtotime()处理非法字符串时会返回false,date("Y-m-d", false)会直接生成1970-01-01,这个值符合你设置的date_format:Y-m-d校验规则,所以不会触发格式报错。 - 校验规则不匹配:用户实际输入的是
d/m/Y格式的日期,你却针对转换后的Y-m-d做校验,完全没有对用户原始输入做合法性校验。 - 转换逻辑无有效性判断:没有判断
strtotime()的返回值是否合法,直接把转换后的错误日期写入请求参数。
修复方案
步骤1:调整校验规则,直接校验用户原始输入
把校验规则改为针对用户输入的d/m/Y格式做校验,不要提前转换日期,非法格式会直接在这一步触发报错:
'date_of_birth' => [ 'required', 'bail', // 直接校验用户输入的格式为d/m/Y,非法内容直接抛出格式错误 'date_format:d/m/Y', function ($attribute, $value, $fail) { // 前面已经校验过格式,这里转换不会报错 $birthDate = \Carbon\Carbon::createFromFormat('d/m/Y', $value); $age = $birthDate->age; if ($age < 18 || $age > 70) { $fail('Âge invalide. l\'âge devrait être 18-70'); } } ]
校验阶段不需要手动修改请求参数的格式,Laravel校验失败后会自动返回用户原始输入用于表单回显,不需要你手动转格式再merge回请求。
步骤2:校验通过后再做格式转换,加有效性判断
控制器里只有校验通过后才执行日期转换,加一层时间戳有效性判断做兜底:
if (!empty($request->date_of_birth)) { $date = str_replace('/', '-', $request->date_of_birth); $timestamp = strtotime($date); // 只有时间戳有效时才做转换 if ($timestamp !== false) { $new_bday = date("Y-m-d", $timestamp); $request->merge(['date_of_birth' => $new_bday]); } else { // 兜底逻辑,极端情况未被校验拦住时返回错误 return back()->withErrors(['date_of_birth' => '日期格式无效,请输入正确的生日'])->withInput(); } }
内容的提问来源于stack exchange,提问作者Volka Dimitrev
相关产品推荐
相关产品推荐

