2014-07-25 14 views
7

Pracuję nad aplikacją, która pozwala użytkownikowi edytować kilka dat w formularzu. Daty są renderowane w formacie europejskim (DD-MM-RRRR), a bazy danych używają domyślnego formatu RRRR-MM-DD.Jak obsługiwać wprowadzanie danych do daty w Laravel

Istnieje kilka sposobów, aby kodują/dekodować te dane iz powrotem z bazy danych do użytkownika, ale wszystkie one wymagają dużo kodu:

  • użyć funkcji pomocnika przekonwertować datę przed zapisaniem i po pobraniu (bardzo kłopotliwe, wymaga dużo kodu)
  • Utwórz osobny atrybut dla każdego atrybutu data i użyć metod setNameAttribute i getNameAttribute dekodowanie/kodowanie (również kłopotliwe i brzydkie, wymaga dodatkowych tłumaczeń/zasady dla każdego atrybutu)
  • Skorzystaj z JavaScript, aby konwertować daty, gdy loa ding i przesłanie formularza (niezbyt wiarygodne)

Jaki jest najskuteczniejszy sposób przechowywania, wyszukiwania i sprawdzania dat i godzin od użytkownika?

+0

Czy wyglądasz, jeśli możesz osiągnąć to, co chcesz, używając węgla, który jest wbudowany w laravel? – MikeWu

+0

Sam datowanie parsowania nie jest problemem, już używam węgla do tego. Problem polega na tym, gdzie umieścić kod do konwertowania dat, nie chcę dodawać ton powtarzających się kodów konwersji w kontrolerach/widokach. Również Carbon zgłasza wyjątek podczas próby parsowania daty o niewłaściwym formacie, co nie jest idealne w przypadku wprowadzania danych przez użytkownika. – Arne

Odpowiedz

7

W pewnym momencie należy przekonwertować datę z formatu widoku na format bazy danych. Jak już wspomniałeś, jest wiele miejsc do zrobienia, w zasadzie wybierając między zapleczem a frontendem.

Wykonuję konwersję po stronie klienta (front-end) przy użyciu javascript (można użyć http://momentjs.com, aby pomóc w tym). Powodem jest to, że możesz potrzebować różnych formatów w zależności od ustawień narodowych, z których korzysta klient (na przykład w przeglądarce lub w ustawieniach profilu). Konwersja formatu w interfejsie frontowym pozwala łatwo konwertować na te różne formaty daty.

Kolejną zaletą jest to, że można wtedy użyć właściwości protected $dates w modelu mieć laravel uchwyt (get i set) te daty automatycznie jako obiekt węgla, bez potrzeby, aby to zrobić (patrz https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L126).

chodzi o walidacji, konieczne może następnie wykorzystać wbudowane reguły sprawdzania poprawności laravel za datami, tak:

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

"Powinieneś użyć daty lub daty w przypadku sprawdzania poprawności pola, a nie obu." - [Laravel Docs] (https://laravel.com/docs/5.2/validation#rule-date-format) – M165437

2

Podczas gdy po stronie klienta jest dobre dla UX, nie pozwalają mieć pewność, wszystko będzie dobrze.

W pewnym momencie będziesz potrzebować walidacji/konwersji po stronie serwera.

Ale chodzi o to, że to tak proste, jak to:

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


Oczywiście, można użyć genialny Carbon aby jeszcze łatwiej:

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

Validation

Mówisz, że Carbon zgłasza wyjątek, jeśli wyposażony niewłaściwego wejścia .Oczywiście, ale tutaj jest to, czego potrzebujesz, aby potwierdzić datę:

'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 

Ten regex jest to konieczne, jeśli chcesz, aby rok część na pewno jest 4digit, ponieważ PHP będzie data 01-02-14 ważny rozważyć, pomimo korzystania Y formatu znaków (co roku = 0014).

1

Najlepszym sposobem, jaki znalazłem, jest przesłonięcie fromDateTime z 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); 
    } 
} 

Jestem nowy w PHP, więc nie wiem, czy to najlepsze podejście. Mam nadzieję, że to pomaga.

Edit:

Oczywiście, należy pamiętać, aby ustawić wszystkie swoje właściwości daty dates wewnątrz modelu. np .:

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