Как обрабатывать ввод даты в 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');