Try T.M Engineer Blog

多摩市で生息するエンジニアが「アウトプットする事は大事だ」と思って始めたブログ

(Laravel第4回目)フォーム、バリデーション、エラーメッセージ日本語化を学んだ話

Laravel第4段です。
今回は(7)まで、進めたので、その復習(アウトプット)をしたいと思います。 参考にしたサイトは以下。

www.hypertextcandy.com

(7)の作成時点

f:id:special-moucom:20190818221213p:plain

(4)から(7)までに学んだこと

(4)から(7)までに以下について学んだので、1つずつ振り返りたいと思います。

  • フォームのCSRF対策
  • フォームの入力値バリデーション
  • エラーメッセージ日本語化

フォームのCSRF対策

フォームに以下のように@csrfと書くことで、簡単にCSRF対策ができます。

<form action="{{ route('folders.create') }}" method="post">
  @csrf
  <div class="form-group">
    <label for="title">フォルダ名</label>
    <input type="text" class="form-control" name="title" id="title" value="{{ old('title') }}"/>
  </div>
  <div class="text-right">
    <button type="submit" class="btn btn-primary">送信</button>
  </div>
</form>

クロスサイトリクエストフォージェリCSRF)とは

クロスサイトリクエストフォージェリCSRF)とは、Webアプリケーションに存在する脆弱性、もしくはその脆弱性を利用した攻撃方法のことです。掲示板や問い合わせフォームなどを処理するWebアプリケーションが、本来拒否すべき他サイトからのリクエストを受信し処理してしまいます。

■参考URL

クロスサイトリクエストフォージェリ(CSRF) | トレンドマイクロ

@csrfは、フォームを表示した時にCSRFトークンを含んだinput要素を出力します。 そのCSRFトークンをセッション内に予め保存しておき、フォームからリクエストが送信されたときに、リクエストに含まれるCSRFトークンとセッション内に保存したトークンの一致確認をして、リクエストが本人から送信されたことを確認しているようです。 この1度しか使われないトークンは、ワンタイムトークンと呼ばれています。

フォームの入力値バリデーション

Laravelは、リクエストに対するバリデーションをコントローラから切り離して定義できます。
それが、FormRequestです。

以下コマンドを使えばFormRequest用のクラスを作成できます。

php artisan make:request CreateTask

詳細は以下を参照ください。
バリデーションの定義はrules関数内で定義します。attributes関数では、入力項目(name)に対する日本語名を定義できたり、message関数では、バリデーションのエラーメッセージを追加できたりします。便利だ(= = ;;)

<?php

namespace App\Http\Requests;

use Illuminate\Foundation\Http\FormRequest;

class CreateTask extends FormRequest
{
    // リクエストを受け付ける場合はtrue
    public function authorize()
    {
        return true;
    }

    // ここでバリデーションルールを設定
    public function rules()
    {
        return [
            'title' => 'required|max:100',
            // after_or_equal の引数として today を指定することにより今日を含んだ未来日だけを許容
            'due_date' => 'required|date|after_or_equal:today',
        ];
    }

    // 入力項目(name)の日本語化 ・・・ 入力項目(name)でバリデーションエラーが発生した時に表示する日本語名を指定
    public function attributes()
    {
        return [
            'title' => 'タイトル',
            'due_date' => '期限日',
        ];
    }

    // バリデーションエラーのメッセージ追加
    public function message()
    {
        return [
            // キーでメッセージが表示されるべきルールを指定する。
            // ドット区切りで左側が項目、右側がルールを意味する。
            // due_date の after_or_equal ルールに違反した場合は、値に指定されたメッセージを出力する
            // 一般的なルールについては validation.php に記述するが、messagesメソッドでは個別の FormRequestクラスの内部でのみ有効なメッセージを定義できる
            'due_date.after_or_equal' => ':attribute には今日以降の日付を入力してください。',
        ];
    }
}

さて、このFormRequest・・・どこで呼ばれているのでしょう? FormRequestはコントローラから切り離して定義したものなので、コントローラを見てみましょう。

class TaskController extends Controller
{
// ・・・省略・・・ //

    public function create(int $id, CreateTask $request)
    {
        $current_folder = Folder::find($id);

        $task = new Task();
        $task->title = $request->title;
        $task->due_date = $request->due_date;
    
        $current_folder->tasks()->save($task);
    
        return redirect()->route('tasks.index', [
            'id' => $current_folder->id,
        ]);
    }

// ・・・省略・・・ //
}

ありました。 createの引数から呼ばれていますね。これがDIなんですね。

DIとは?

「依存性の注入」(Dependency injection)のこと。
クラスと依存関係にあるオブジェクトを外から渡す事で、依存レベルをさらに下げることができる方法です。
今回で言えば、TaskControllerクラスとCreateTaskクラスは依存関係にありますが、CreateTaskクラスはTaskControllerクラスから切り離して定義して、オブジェクトとして外から渡しています。

エラーメッセージ日本語化

メッセージ関連の設定は resources/lang ディレクトリで管理されています。 最初、enフォルダしかないので、jpフォルダを新しく作成して、そこにメッセージを格納するようにしていきます。

それに伴い、app.phpファイルも修正します。

'locale' => 'jp',

'fallback_locale' => 'en',

あとは、各々のphpファイルを日本語に修正するだけで、メッセージが日本語になります。

うーん、学びが多い(= = ;; )