Как обрабатывать ввод даты в Laravel

Я работаю на приложение, которое позволяет пользователю редактировать несколько дат в форме. Даты отображаются в европейском формате (DD-MM-YYYY), в то время как базы данных используют формат YYYY-MM-DD по умолчанию.

Существует несколько способов кодирования/декодирования данных из базы данных пользователь, но все они требуют много кода:

  • используйте вспомогательную функцию для преобразования даты перед сохранением и после извлечения (очень громоздкий, требует много код)
  • создайте отдельный атрибут для каждого атрибута даты и используйте setNameAttribute и getNameAttribute методы декодирования / кодирования (также громоздкие и уродливые, требуют дополнительных переводов/правил для каждого атрибута)
  • используйте JavaScript для преобразования дат при загрузке и отправке формы (не очень надежно)

Итак, каков наиболее эффективный способ хранения, извлечения и проверки дат и времени от пользователя?

3 ответов


в какой-то момент, Вы должны преобразовать дату из формата в формат базы данных. Как вы упомянули, есть несколько мест для этого, в основном выбирая между задней или передней частью.

Я делаю преобразование на стороне клиента (front-end) с помощью javascript (вы можете использоватьhttp://momentjs.com чтобы помочь с этим). Причина в том, что вам могут понадобиться разные форматы в зависимости от используемой клиентом локали (установленной в браузере или в его например, настройки профиля). Выполнение преобразования формата в интерфейсе позволяет легко конвертировать в эти различные форматы даты.

еще одно преимущество заключается в том, что вы можете использовать protected $dates свойство в вашей модели иметь дескриптор Laravel (get и set) эти даты автоматически как объект Carbon, без необходимости делать это (см. https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L126).

Как для проверки вам нужно использовать встроенные правила проверки Laravel для дат, например:

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

в то время как клиентская сторона хороша для UX, она не позволяет вам быть уверенным, все будет хорошо.

в какой-то момент вам все равно понадобится проверка/конвертация на стороне сервера.

но вот в чем дело, это так просто, как это:

// 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!


очевидно, вы можете использовать brilliant чтобы сделать его еще проще:

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

проверка

вы говорите, что Углерод бросает исключение, если при неправильном вводе. Конечно, но вот что вам нужно для проверки даты:

'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

эта часть regex необходима, если вы хотите убедиться, что часть года 4digit, так как PHP будет рассматривать дату 01-02-14 действительно, несмотря на использование Y символьный формат (год = 0014).


лучший способ, который я нашел, - переопределить fromDateTime С 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);
    }
}

Я новичок в PHP, поэтому я не знаю, лучший ли это подход. Надеюсь, это поможет.

Edit:

конечно, не забудьте установить все свойства, нужные в dates внутри вашей модели. например:

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