如何处理 Laravel 中的日期输入

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24965799/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-09 02:54:17  来源:igfitidea点击:

How to handle date input in Laravel

formsdatelaravellocalizationformatting

提问by Arne

I'm working on an app that allows the user to edit several dates in a form. The dates are rendered in the European format (DD-MM-YYYY) while the databases uses the default YYYY-MM-DD format.

我正在开发一个允许用户在表单中编辑多个日期的应用程序。日期以欧洲格式 (DD-MM-YYYY) 呈现,而数据库使用默认的 YYYY-MM-DD 格式。

There are several ways to encode/decode this data back and forth from the database to the user, but they all require a lot of code:

有几种方法可以将这些数据从数据库到用户来回编码/解码,但它们都需要大量代码:

  • Use a helper function to convert the date before saving and after retrieving (very cumbersome, requires much code)
  • Create a separate attribute for each date attribute, and use the setNameAttributeand getNameAttributemethods to decode/encode (also cumbersome and ugly, requires extra translations/rules for each attribute)
  • Use JavaScript to convert the dates when loading and submitting the form (not very reliable)
  • 使用helper函数转换保存前和检索后的日期(很麻烦,需要很多代码)
  • 为每个日期属性创建一个单独的属性,并使用setNameAttributegetNameAttribute方法进行解码/编码(也很麻烦和丑陋,每个属性都需要额外的翻译/规则)
  • 加载和提交表单时使用 JavaScript 转换日期(不太可靠)

So what's the most efficient way to store, retrieve and validate dates and times from the user?

那么,从用户那里存储、检索和验证日期和时间的最有效方法是什么?

采纳答案by lowerends

At some point, you have to convert the date from the view format to the database format. As you mentioned, there are a number of places to do this, basically choosing between the back-end or the front-end.

在某些时候,您必须将日期从视图格式转换为数据库格式。正如你提到的,有很多地方可以做到这一点,基本上是在后端或前端之间进行选择。

I do the conversion at the client side (front-end) using javascript (you can use http://momentjs.comto help with this). The reason is that you may need different formats depending on the locale the client is using (set in the browser or in his profile preferences for example). Doing the format conversion in the front-end allows you to convert to these different date formats easily.

我使用 javascript 在客户端(前端)进行转换(您可以使用http://momentjs.com来帮助解决这个问题)。原因是您可能需要不同的格式,具体取决于客户端使用的区域设置(例如在浏览器中或在他的配置文件首选项中设置)。在前端进行格式转换可以让您轻松转换为这些不同的日期格式。

Another advantage is that you can then use the protected $datesproperty in your model to have Laravel handle (get and set) these dates automatically as a Carbon object, without the need for you to do this (see https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L126).

另一个优点是,您可以使用protected $dates模型中的属性让 Laravel 将这些日期作为 Carbon 对象自动处理(获取和设置),而无需您执行此操作(请参阅https://github.com/laravel/框架/blob/master/src/Illuminate/Database/Eloquent/Model.php#L126)。

As for validation, you need can then use Laravel's built-in validation rules for dates, like this:

至于验证,您需要然后可以使用 Laravel 的内置日期验证规则,如下所示:

'date' => 'required|date|date_format:Y-n-j'

回答by Jarek Tkaczyk

While client-side is good for UX, it doesn't let you be sure, all will be good.

虽然客户端有利于用户体验,但它并不能让您确定,一切都会好起来的。

At some point you will need server-side validation/convertion anyway.

在某些时候,您无论如何都需要服务器端验证/转换。

But here's the thing, it's as easy as this:

但事情就是这样,就这么简单:

// after making sure it's valid date in your format
// $dateInput = '21-02-2014'

$dateLocale = DateTime::createFromFormat('d-m-Y', $dateInput);

// or providing users timezone
$dateLocale = 
   DateTime::createFromFormat('d-m-Y', $dateInput, new DateTime('Europe/London'));

$dateToSave = $dateLocale
           // ->setTimeZone(new TimeZone('UTC'))   if necessary
           ->format('Y-m-d');

et voila!

等等!



Obviously, you can use brilliant Carbonto make it even easier:

显然,您可以使用出色的Carbon使其更容易:

$dateToSave = Carbon::createFromFormat('d-m-Y', $dateInput, 'Europe/London')
        ->tz('UTC')
        ->toDateString(); // '2014-02-21'


Validation

验证

You say that Carbon throws exception if provided with wrong input. Of course, but here's what you need to validate the date:

你说如果提供了错误的输入,Carbon 会抛出异常。当然,但这是验证日期所需的内容:

'regex:/\d{1,2}-\d{1,2}-\d{4}/|date_format:d-m-Y'

// accepts 1-2-2014, 01-02-2014
// doesn't accept 01-02-14

This regex part is necessary, if you wish to make sure year part is 4digit, since PHP would consider date 01-02-14valid, despite using Yformat character (making year = 0014).

这个正则表达式部分是必要的,如果你想确保年份部分是 4digit,因为 PHP 会认为日期01-02-14有效,尽管使用Y格式字符(使 year = 0014)。

回答by Kim Tranjan

The best way I found is overriding the fromDateTimefrom Eloquent.

我发现的最好方法是覆盖fromDateTimefrom Eloquent

class ExtendedEloquent extends Eloquent {
    public function fromDateTime($value)
    {
        // If the value is in simple day, month, year format, we will format it using that setup.
        // To keep using Eloquent's original fromDateTime method, we'll convert the date to timestamp,
        // because Eloquent already handle timestamp.
        if (preg_match('/^(\d{2})\/(\d{2})\/(\d{4})$/', $value)) {
            $value = Carbon\Carbon::createFromFormat('d/m/Y', $value)
                ->startOfDay()
                ->getTimestamp();
        }

        return parent::fromDateTime($value);
    }
}

I'm new in PHP, so I don't know if it's the best approach. Hope it helps.

我是 PHP 新手,所以我不知道这是否是最好的方法。希望能帮助到你。

Edit:

编辑:

Of course, remember to set all your dates properties in datesinside your model. eg:

当然,请记住在dates模型中设置所有日期属性。例如:

protected $dates = array('IssueDate', 'SomeDate');