1970-01-01 当用户尝试在 laravel 的日期字段中输入文本而不显示错误时,存储在数据库中

1970-01-01 stores in the DB when a user tries to input a text in the date field in laravel without showing en error

在我的 laravel 应用程序中,我有一个用于注册新用户的表格。

在那个表格中,我有一个输入用户生日的字段。

即使我以 d/m/Y 格式获取用户输入日期,在将它们保存到数据库之前,我也会从我的控制器将它们转换为 Y-m-d

if(!empty($request->date_of_birth)){

                $date = str_replace('/', '-', $request->date_of_birth);
                $new_bday=date("Y-m-d", strtotime($date) );
                $request->merge(['date_of_birth' => ''.$new_bday.'']);    

            }

我对生日字段有以下验证规则。

'date_of_birth'=>['required','bail','date_format:Y-m-d',function ($attribute, $value, $fail) {

                $age=Carbon::createFromFormat('Y-m-d', $value)->diff(Carbon::now())->y;
                if($age<18||$age>70){
                    $date = str_replace('-', '/', $value);
                    $new_bday=date("d/m/Y", strtotime($date) );
                    \request()->merge(['date_of_birth' => ''.$new_bday.'']);
                    $fail('Âge invalide. l\'âge devrait être 18-70');
                }

            },] 

但现在的问题是,

如果用户尝试输入文本(如 test)而不是从日期选择器中选择日期并尝试提交表单,它会验证并在数据库中保存 1970-01-01

用例 - 用户在生日字段中键入“你好”并保存表单。 1970-01-01 将被存储为生日

如何在用户尝试插入无效输入时显示正确的验证消息并避免保存 1970-01-01...

当然更好的解决办法是首先不让他们输入除日期以外的任何内容?最简单的,使用

<input type="date" required>

会强制他们输入日期格式,并禁止自由输入,这样他们就无法输入“测试”。由于这会导致 MySQL 接受 (Y-m-d) 的格式,因此您不必对控制器中的输入做任何事情。

您存储了错误的日期字符串,这就是为什么得到 1970-01-01

dump/debug存储前的日期。

以下代码可能会解决您的问题

if($request->date_of_birth) {
    $date = \Carbon\Carbon::createFromFormat('d/m/Y', $request->date_of_birth)->format('Y-m-d');

    $request->merge(['date_of_birth' => $date]);
}

您的问题是您使用 strtotime() 转换了用户提供的值,而没有先检查它。 strtotime('test') 将 return falsedate() 解释为 0,即 1970。然后在自定义验证函数中,您尝试在请求失败之前再次进行此转换出于某种原因。

假设您使用的是表单请求,您的代码应如下所示:

<?php
namespace App\Http\Requests;

use Carbon\Carbon;
use Carbon\Exceptions\InvalidFormatException;
use Illuminate\Foundation\Http\FormRequest;

class StoreUser extends FormRequest
{
    protected function prepareForValidation()
    {
        // convert from user-input d/m/Y format if possible
        try {
            $birthday = Carbon::createFromFormat('d/m/Y', $this->date_of_birth);
            $this->replace(['date_of_birth' => $birthday->format('Y-m-d')]);
        } catch (InvalidFormatException) {
            return;
        }
    }

    public function rules()
    {
        return [
            'date_of_birth' => [
                'required',
                'bail',
                'date_format:Y-m-d',
                function ($attribute, $value, $fail) {
                    $age = Carbon::createFromFormat('Y-m-d', $value)->age;
                    if($age < 18 || $age > 70) {
                        $fail('Âge invalide. l\'âge devrait être 18-70');
                    }
                }
            ],
        ];
    }
}