Laravelはスタート&終了(防止ダブルブッキング)の間の時間であります

デイモン:

私は確かに新しい予約が別の別の上でダブルブッキングすることができないことを確認するためのテストを書いています。私は無数の他のSOスレッドかかわらず読んで、今私はもっと混乱していると確認してください私は何の権利をやっているではありません。私は、特に私のプロジェクトと同様に、この例ではLaravelを使用しています。

Migration.php

...
$table->date('date');       // 2020-01-01
$table->time('time_start'); // 15:00:00
$table->time('time_end');   // 17:00:00
...

私が働いてきましたdateTimetimezone私は「私はしていない、のトラップに入る必要がある日付、時間だけが。私はどこか別の日付を保存しています。」私はその後で保存を示唆しているスレッドを見つけることができますtimestampし、そこにも日付を比較します。

私は(その他の詳細の中で)生成するために、予約の工場を持っているdatetime_starttime_end

Factory.php

'date' => date('Y-m-d'),
'time_start' => '15:00:00',
'time_end' => '17:00:00',

私が読んだほとんどのスレッドが使用して比較することをお勧めstrtotime何かのようなもの:

'time_start' => strtotime('15:00:00'),  // 1582210800

意味あり。しかし、私はとして保存することを読まdateTimeまたはtimezoneより良いので、タイムゾーンです。

私のコントローラでは私はこのような既存の予約をチェックしています:

Controller.php

...
$existing = DB::table('reservations')
    ->where('asset_id', '=', $request->asset_id)
    ->whereDate('date', '=', $request->date)
    ->whereTime('time_start', '>=', $request->time_start)  // or use $request->strtotime('time_start')
    ->whereTime('time_end', '<=', $request->time_end)
    ->where(function ($query) {
        $query
            ->where('status', '=', 'created')
            ->orWhere('status', '=', 'pending')
            ->orWhere('status', '=', 'completed');
    })
    ->get();

if ($existing->count() > 0) {
    // Not allowed
} else {
    // OK to proceed
}
...

使用whereTimeルックスは私が必要とする正確に何が好き:

->whereTime('created_at', '=', '11:20:45') 

それはとして保存されるように見えますtime列。私のテストでは、私は私が得ることを確認しています400、それが作成できない場合はバックを。

test.phpを

...
$http->assertStatus(400)
    ->assertJsonStructure([
        'type', 'data' => [
            'reason'
        ]])
        ->assertJson([
            'type' => 'reservations',
            'data' => [
                'reason' => 'Asset is no longer available.',
            ],
        ]);

これは素晴らしい作品。私は、予約作成する場合15:00:0017:00:00など、同じ日付/資産私のテストパスを。私は戻っまさに私が期待するとして400エラーが発生します。私が合格した場合しかし、15:01:00私のテストは失敗します。ない驚いたが、それは私が正しく比較を扱うわけではないと言われます。私は、フィニッシュラインを右にしていますように思えるが、その後、両方の靴は、アンタイドなってきました。

UIはちょうど人間が読める倍とドロップダウンになります。私はちょうど24時間の時間などの値を保存する上で計画していました。たとえば、15:00:00私は確かにどのように他のことを行うにはありませんよ...

提案は、より良い方法を理解するために、私は感謝されます。

  • ベスト時間(s)の保存timetimestampdatetime
  • 使用するstrtotime(またはしません)。もしそうならば、理想的なデータ型は何ですか?timestampdatetime
  • 適切なエラー応答を使用します。400理想的ですか?

任意の考えのためにありがとうございました。

更新

miken32提案@に続いて-私がやったことは意味を成していたので、すでにそのように設定する関係を持っています。

私は今、保存していますtime_starttime_endとしてdateTimeの私の移動のフィールド。

Controller.php

$asset = Asset::find($request->asset_id);

$existing = $asset->reservations()
    ->where(function ($query) use ($request) {
        $start_dt = new Carbon($request->time_start);
        $end_dt = new Carbon($request->time_end);

        $query->where('time_start', '>=', $start_dt)
            ->where('time_end', '<=', $end_dt);
        })
        ->whereIn('status', ['created', 'pending', 'completed'])
        ->get();

    if ($existing->count() > 0) {
        // Log::info('CANNOT MAKE RESERVATION FOR: ' . $request->first_name . ' ' . $request->last_name);
        return response()->json(['type' => 'reservations', 'data' => ['reason' => 'Asset is no longer available.']], 409);
    } else {
        $reservation = new Reservation();
        ...
        // Log::info('RESERVATION MADE FOR: ' . $reservation->first_name . ' ' . $reservation->last_name);

ユーザーは、事前に決められた時間(秒)を選択するオプションがあります。タイムスロットは、任意の資産のために予約されたならば、そのブロックは未使用可能です。私は、私は誰かが(何らかの形で)をオーバーライドすることができないことを確認すること本質的にだと確信POST異なる値とリクエストを。

うまくいけば、これは他の誰かを助けます。私の実装がオフの場合、私は皆のためにそれを修正することができますので、私に知らせてください。

miken32:

次の2つのように、この情報を格納したほうが良いでしょうDATETIME列。利点はLaravelの組み込みカーボン日付にキャストを利用することができること、そして深夜上で予約の予定とのトラブルを避けることがあります。

次に、仮定$request->time_startおよび$request->time_endクエリは次のようなものとなり、完全な日付/時刻を以下のとおりです。

$existing = DB::table('reservations')
    ->where('asset_id', $request->asset_id)
    ->where(function($q) {
        $q->whereBetween('time_start', [$request->time_start, $request->time_end])
            ->orWhereBetween('time_end', [$request->time_start, $request->time_end]);
    })
    ->whereIn('status', ['created', 'pending', 'completed'])
    ->get();

あなたはまた、追加のだtime_starttime_end、あなたのモデルのへ$datesの利点を活用するために、アレイ自動キャスト

あなたの関係が正しく設定されている場合やモデルといえば、このクエリの代わりに使用するのでは、このようなことができDBファサードを:

$asset = Asset::find($request->asset_id);
$existing = $asset
    ->reservations()
    ->where(function($q) {
        $q->whereBetween('time_start', [$request->time_start, $request->time_end])
            ->orWhereBetween('time_end', [$request->time_start, $request->time_end]);
    })
    ->whereIn('status', ['created', 'pending', 'completed'])
    ->get();

それは何の短いませんが、IMOそれは検索されているものを一目で確認することが容易になります。


HTTPレスポンスに関しては、本当にあなたが使用しているものは問題ではありません。あなたが期待するものを知っているので、それは、すべてのコードです。しかし、あなたは(私は完全にサポート)杓子定規多分になりたい場合は409、あなたのニーズに合うのでしょうか?

409(競合)ステータスコードは、要求がターゲットリソースの現在の状態との競合による完了できなかったことを示しています。このコードは、ユーザーが競合を解決し、要求を再送信することができるかもしれない状況で使用されています。サーバは、ユーザが競合のソースを認識するための十分な情報を含むペイロードを生成する必要があります。

おすすめ

転載: http://43.154.161.224:23101/article/api/json?id=8830&siteId=1