web-dev-qa-db-ja.com

Laravel)での日付入力の処理方法

私は、ユーザーがフォーム内の複数の日付を編集できるようにするアプリに取り組んでいます。日付はヨーロッパ形式(DD-MM-YYYY)で表示されますが、データベースはデフォルトのYYYY-MM-DD形式を使用します。

このデータをデータベースとユーザーの間でエンコード/デコードする方法はいくつかありますが、それらはすべて多くのコードを必要とします。

  • ヘルパー関数を使用して、保存前と取得後に日付を変換します(非常に面倒で、多くのコードが必要です)
  • 日付属性ごとに個別の属性を作成し、setNameAttributeおよびgetNameAttributeメソッドを使用してデコード/エンコードします(これも面倒で醜いため、属性ごとに追加の変換/ルールが必要です)
  • JavaScriptを使用して、フォームを読み込んで送信するときに日付を変換します(信頼性はあまり高くありません)

では、ユーザーから日付と時刻を保存、取得、検証するための最も効率的な方法は何でしょうか。

7
Arne

ある時点で、日付をビュー形式からデータベース形式に変換する必要があります。あなたが言ったように、これを行う場所はたくさんあり、基本的にバックエンドかフロントエンドのどちらかを選択します。

私はjavascriptを使用してクライアント側(フロントエンド)で変換を行います(これを支援するために http://momentjs.com を使用できます)。その理由は、クライアントが使用しているロケールに応じて異なる形式が必要になる場合があるためです(たとえば、ブラウザーまたはプロファイル設定で設定します)。フロントエンドでフォーマット変換を行うと、これらの異なる日付フォーマットに簡単に変換できます。

もう1つの利点は、モデルのprotected $datesプロパティを使用して、Laravelがこれらの日付をCarbonオブジェクトとして自動的に処理(取得および設定)できることです。これを行う必要はありません( https://github.com/laravel/framework/blob/master/src/Illuminate/Database/Eloquent/Model.php#L126 を参照してください。

検証に関しては、次のように、Laravelの組み込みの検証ルールを日付に使用する必要があります。

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

クライアントサイドは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 Carbon を使用すると、さらに簡単になります:

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

検証

間違った入力が提供された場合、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

Y形式の文字を使用しているにもかかわらず、PHPは日付01-02-14を有効と見なすため、年の部分が4桁であることを確認する場合は、この正規表現の部分が必要です(年= 0014)。

2
Jarek Tkaczyk

私が見つけた最良の方法は、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を初めて使用するので、それが最善のアプローチかどうかはわかりません。それが役に立てば幸い。

編集:

もちろん、モデル内のdatesにすべての日付プロパティを設定することを忘れないでください。例えば:

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