after — 指定日以降であることを検証する

validation
  • カテゴリ: validation
  • 掲載バージョン: Laravel 12・PHP 8.4
  • 名前空間 / FQCN / コマンド: after:date / Illuminate\Validation\Rule::after()
  • 関連: after_or_equal / before / before_or_equal / date / date_format
  • 変更履歴: Laravel 5.x から提供。Rule::after() による fluent 指定は 5.5+。

要点(TL;DR)

  • 入力がある基準日より後かをチェックするルール
  • ['ends_at' => 'required|date|after:starts_at']
  • 罠:比較対象の形式ミスマッチタイムゾーン差date 未付与で文字列比較になる

概要

after は日時入力が、指定した基準日時より未来側であることを検証します。基準は固定日付他フィールドnow(現在時刻)のいずれかで指定できます。日付文字列は date / date_format などと組み合わせ、パース可能な日時として扱えるようにするのが実務の基本です。

構文 / シグネチャ

// バリデーションルール(文字列)
'field' => 'after:<date_or_field|now>'

// ルールオブジェクト(fluent)
use Illuminate\Validation\Rule;

'field' => [Rule::after('<date_or_field|now>')]

引数(表)

引数必須既定値説明
date_or_fieldstringYesなしYYYY-MM-DD 等の絶対日付、field_name(他フィールド参照)、または now

  • 戻り値:検証成功/失敗(バリデータ全体として Illuminate\Contracts\Validation\Validator が true/false)
  • 例外/副作用:該当フィールドが検証失敗時にエラーメッセージ生成。副作用なし。

使用例

最小例

use Illuminate\Support\Facades\Validator;

$data = [
    'starts_at' => '2025-10-10 10:00:00',
    'ends_at'   => '2025-10-10 12:00:00',
];

$rules = [
    'starts_at' => ['required','date'],
    'ends_at'   => ['required','date','after:starts_at'],
];

$validator = Validator::make($data, $rules);

if ($validator->fails()) {
    // エラー処理
}

実務例(FormRequest・現在時刻との比較)

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Validation\Rule;

class PublishRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title'      => ['required','string','max:120'],
            'starts_at'  => ['required','date','after:now'], // 未来スケジュールのみ許可
            'ends_at'    => ['required','date','after:starts_at'],
        ];
    }

    public function messages(): array
    {
        return [
            'ends_at.after'   => '終了日時は開始日時より後で指定してください。',
            'starts_at.after' => '開始日時は現在より後の時刻を指定してください。',
        ];
    }
}

よくある落とし穴・注意

  • date を併用するafter 単体だとパース不能な文字列の扱いが曖昧になりがち。date/date_format と併用して必ず日時として解釈させる。
  • フォーマットの一貫性date_format:Y-m-d H:i を両フィールドに付け、同じ書式で比較させる。
  • タイムゾーン:アプリの config('app.timezone') とユーザー入力のタイムゾーン差異で境界ズレが起きる。受け取りを UTC で統一するか、明示的にタイムゾーンを含む書式にする。
  • 境界条件:同一時刻は失敗。同値を許容するなら after_or_equal を使う。
  • 他フィールド未入力after:starts_atstarts_at が空だと期待通り動かないケース。required_with:ends_at などで依存関係を定義。

代替・関連APIとの比較

  • after_or_equal:同一時刻を許容する場合に選択。
  • before / before_or_equal:過去側の制約が必要な場合。
  • date / date_formatafter必ずセットで使い、解釈の曖昧さを排除。
  • Rule::after():配列定義で可読性を上げたい/条件分岐で柔軟に指定したい場合に有用。

通過/失敗ケース(代表例)

入力値 (starts_at / ends_at)ルール結果ポイント
2025-10-10 10:00 / 2025-10-10 12:00ends_at: after:starts_at通過12:00 は 10:00 より後
2025-10-10 10:00 / 2025-10-10 10:00after:starts_at失敗同一は不可
2025-10-10 / 2025-10-09after:starts_at失敗過去側
now より未来after:now通過現在時刻より後
2025/10/10(スラッシュ)`date_format:Y-m-dafter:…`失敗

テスト例(Pest)

<?php

use Illuminate\Support\Facades\Validator;

it('validates ends_at is after starts_at', function () {
    $data = [
        'starts_at' => '2025-10-10 10:00:00',
        'ends_at'   => '2025-10-10 10:00:01',
    ];

    $rules = [
        'starts_at' => ['required','date','date_format:Y-m-d H:i:s'],
        'ends_at'   => ['required','date','date_format:Y-m-d H:i:s','after:starts_at'],
    ];

    $v = Validator::make($data, $rules);

    expect($v->passes())->toBeTrue();
});

トラブルシュート(エラー別)

症状/エラー原因対処
「The ends at must be a date after starts at.」ends_at が同一または過去after_or_equal の検討、入力調整
想定外に通る/落ちるフォーマット不一致や date 未併用date/date_format を両方へ付与
ローカルと本番で判定がズレるTZ 差(app.timezone入力を UTC に正規化/TZ を明示
他フィールド参照で常に失敗参照先が未入力required_with / required の組み合わせで依存性を担保

参考リンク

長野県・北アルプス地方在住のフリーランスWebプログラマー。
「落ち着くためのWeb開発」をテーマに、訪れる人が安心して使えるサービスづくりを心がけています。

LaravelやWordPressなどのWebアプリケーション開発を得意とし、技術面の安定性はもちろん、運用後も長く活用できる設計を大切にしています。
静かな山間の暮らしから生まれる視点で、シンプルかつ本質的な解決策をご提案します。

野鳥観察も趣味のひとつで、特にミソサザイ(Wren)に魅力を感じています。
小さな体に反して力強く上向きの尾羽、そして澄んだ鳴き声が遠くまで響く姿に、静かな存在感と芯の強さを感じます。
このサイト名「Laravel Wren」には、そんなミソサザイのように、小さくても確かな価値を届けたいという想いを込めています。

信頼できるパートナーとして、そして気軽に相談できる存在として、あなたのWebプロジェクトをサポートします。

Yudai Tsuyuzakiをフォローする