Laravel

フォームとバリデーション

入力値を検証し、失敗時も利用者がやり直しやすい画面を作りましょう。

01

フォームを安全に送信する

WebルートのPOSTフォームにはCSRFトークンを埋め込みます。入力値はoldで保持し、送信先は名前付きルートから作ります。

create.blade.phpBLADE
<form method="POST" action="{{ route('posts.store') }}">
    @csrf
    <label for="title">タイトル</label>
    <input id="title" name="title" value="{{ old('title') }}">
    <textarea name="body">{{ old('body') }}</textarea>
    <button type="submit">保存</button>
</form>
CSRFを省略しない トークンがないPOSTは、LaravelのWebミドルウェアで拒否されます。GETで状態を変更する設計にしてトークンを避ける方法も安全ではありません。
02

バリデーションルールを書く

必須、型、長さ、範囲、重複などをルールとして宣言します。受け取った値を検証し、通過した値だけを保存処理へ渡します。

ControllerPHP
$validated = $request->validate([
    'title' => ['required', 'string', 'max:100'],
    'body' => ['required', 'string', 'max:5000'],
    'email' => ['required', 'email'],
    'published_at' => ['nullable', 'date'],
]);

Post::create($validated);

「入力がない」と「空文字を許す」は別です。任意項目にはnullableを付け、数値なら文字列のまま保存せず、ルールとDBの型をそろえます。

03

失敗を画面へ戻す

検証に失敗すると通常は元の画面へリダイレクトされ、エラーと入力値がセッションへ保存されます。Bladeで項目ごとのメッセージを表示します。

エラーと成功表示BLADE
@error('title')
    <p class="error">{{ $message }}</p>
@enderror

@if ($errors->any())
    <p>入力内容を確認してください。</p>
@endif

@if (session('status'))
    <p>{{ session('status') }}</p>
@endif

フォームが複数ある画面では、名前付きエラーバッグを使って別フォームのエラーと混ざらないようにします。

04

Form Requestへまとめる

検証ルールや認可が複雑になったら、Form Requestへ移します。Controllerが短くなり、ルールを単体で読みやすくなります。

作成と利用COMMAND / PHP
php artisan make:request StorePostRequest

// StorePostRequest.php
public function authorize(): bool
{
    return auth()->check();
}

public function rules(): array
{
    return [
        'title' => ['required', 'string', 'max:100'],
        'body' => ['required', 'string', 'max:5000'],
    ];
}

public function store(StorePostRequest $request)
{
    Post::create($request->validated());
}
05

アップロードを検証する

ファイル名や拡張子だけを信用せず、サイズやMIMEタイプを検証します。保存したパスをDBに記録し、表示用URLとの関係を分けます。

フォームとルールBLADE / PHP
<form method="POST" enctype="multipart/form-data">
    @csrf
    <input type="file" name="photo" accept="image/png,image/jpeg">
</form>

'photo' => ['nullable', 'image', 'max:2048'],

$path = $request->file('photo')->store('posts', 'public');
公開範囲を確認 利用者の画像をそのまま実行可能な場所へ置かないでください。保存ディスク、ファイル名、アクセス権、削除時の後片付けを設計します。
PRACTICE

練習問題

プロフィール編集フォームに、名前(必須・50文字以内)、自己紹介(任意・500文字以内)、メールアドレス(必須・メール形式)を追加してください。

確認ポイント
  • POSTに@csrfを含める
  • エラー時もoldで入力を戻す
  • 検証済みの値だけで更新する
  • 自分以外の利用者を更新できないよう認可する