SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

人気のPHPフレームワークLaravelを習得しよう

Laravelにおけるバリデーションを理解しよう

人気のPHPフレームワークLaravelを習得しよう 第8回

  • X ポスト
  • このエントリーをはてなブックマークに追加

Laravelによるバリデーションを組み込む方法

 概論はここまでにして、実際にコードを交えてLaravelのバリデーションを体験していただきます。

入力画面やコントローラの作成

 バリデーションのコードを紹介する前にまず、図1の画面とコントローラクラス、および、そのメソッドのルーティング登録を行いましょう。

 入力画面はリスト1の内容です。

[リスト1]resources/views/chap8/input.blade.php
<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>入力画面</title>
</head>
	<body>
		<h1>入力画面</h1>
		<form action="/firstlaravel/public/chap8/addData" method="post">
			@csrf  // ★
			<label for="name">
				名前: 
				<input type="text" name="name" id="name">
			</label><br>
			<label for="height">
				身長: 
				<input type="text" name="height" id="height">
			</label><br>
			<label for="weight">
				体重: 
				<input type="text" name="weight" id="weight">
			</label><br>
			<label for="note">
				コメント: 
				<textarea name="note" id="note"></textarea>
			</label><br>
			<button type="submit">送信</button>
		</form>
	</body>
</html>

 HTMLの入力チェックはあえて含めないようにしています。なお、リスト1の★については、項末のNoteを参照してください。

 次に、コントローラクラスです。これはリスト2の内容です。

[リスト2]app/Http/Controllers/Chap8Controller.php
<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class Chap8Controller extends Controller
{
	public function showInput()  // (1)
	{
		return view("chap8.input");
	}
	public function addData(Request $request)  // (2)
	{
		// (3)
		return "<h1>入力完了</h1>";  // (4)
	}
}

 ここではメソッドを2個記述しています。(1)がリスト1の入力画面を表示させるメソッドであり、(2)が入力画面の[送信]ボタンをクリックした時に呼び出されるメソッドです。(2)のメソッドに関しては、話を簡単にするために、特に処理を行わず、(4)のように画面に「入力完了」を表示させるだけにしています。この(3)の位置にバリデーション処理を追記していきます。その時に必要となるので、あらかじめ引数としてRequestオブジェクトをもらうようにしています。

 この2メソッドをルーティング登録しましょう。web.phpにリスト3の2行を追記してください。

[リスト3]routes/web.php
Route::get("/chap8/showInput", "Chap8Controller@showInput");
Route::post("/chap8/addData", "Chap8Controller@addData");

 全ての追記が終了したら、次のURLにアクセスして図1の画面が表示されるか確認してください。

  • http://localhost/firstlaravel/public/chap8/showInput

 現状、何もバリデーションを含めていませんので、そのまま[送信]ボタンをクリックすると、画面に「入力完了」と表示されます。

Note:CSRF対策

 Webの脆弱性を利用した攻撃のひとつとしてCSRFというのがあります。これは、クロスサイトリクエストフォージェリ(Cross-Site Request Forgeries)の頭文字を取ったものです。詳細は他媒体に譲りますが、これは本来拒否すべき他サイトからのリクエストを受信し、処理してしまう脆弱性のことです。Laravelには、デフォルトでこのCSRF対策が含まれており、formタグ内に@csrfディレクティブを記述することで実現できます。

Laravelのバリデーションはvalidate()メソッド

 準備が整ったところで、リスト2の(3)にリスト4の太字のコードを追記していきましょう。これが、バリデーションのコードになります。

[リスト4]app/Http/Controllers/Chap8Controller.php
〜省略〜
	public function addData(Request $request)
	{
		$request->validate([  // (1)
			"name" => "required",  // (2)
			"height" => "required|numeric",  // (3)
			"weight" => "required|numeric",  // (4)
		]);
		return "<h1>入力完了</h1>";
	}
}

 Laravelでバリデーションを実行するには、リスト4の(1)のように、引数で渡されたRequestオブジェクトのvalidate()メソッドを実行するだけです。その際、引数として、(2)〜(4)のように、連想配列を渡します。連想配列には、キーとしてコントロールのname属性値、値としてバリデーションルール名を記載します。構文としてまとめると次のようになります。

[構文]バリデーションの実行
$request->validate([
	"name属性値" => "バリデーションルール名",
	 :
]);

 リスト4の(2)では、[名前]入力欄に必須チェックであるrequiredを指定しています。

 [身長]入力欄である(3)と[体重]入力欄である(4)には、同じくrequiredだけでなく、数値かどうかのチェックを行うnumericも指定しています。このように複数のバリデーションを行う場合は「|」(パイプ)を記述して複数並べるか、次のように配列で指定します。

"height" => ["required", "numeric"]

 なお、Laravelに標準で用意されているバルデーションルールはLaravelの公式ドキュメントで確認できます。また、詳細は割愛しますが、独自にルールを追加することもできます。

 一通り、追記が終了したら、動作確認を行っておきましょう。図1の画面が表示された状態で、何も入力せずに[送信]ボタンをクリックしてください。これまで、画面に「入力完了」と表示されていたものが、リスト4の太字のコードを追記した途端、画面が遷移せずにもう一度図1が表示されてしまいます。この種明かしを次節で行なっていきましょう。

バリデーションメッセージの表示

 コントローラにバリデーションのコードを追記した途端、画面遷移しなくなりました。これはどういうことでしょうか。その種明かしをしていきましょう。

バリデーションエラーの場合は入力画面表示URLへリダイレクト

 入力画面から画面遷移しなくなったように見えますが、実は、これは遷移した先でもう一度入力画面に戻ってきているのです。その証拠に、図4のように各入力欄に正しい値を入力した上で[送信]ボタンをクリックした場合は、ちゃんと画面に「入力完了」と表示されます。

図4: 適切な値を入力した入力画面

図4: 適切な値を入力した入力画面

 リスト4の(1)でvalidate()メソッドを実行した際、バリデーションエラーが見つかると、Laravelはそれ以降の処理を続行せずに、自動的に元の入力画面を表示するURLにリダイレクトする仕組みとなっています(図5)。

図5: バリデーションエラーの場合の挙動

図5: バリデーションエラーの場合の挙動

バリデーションメッセージはセッションに一時的に格納

 とはいえ、このままでは何がどうエラーなのか全くわかりません。そこで、Laravelはリダイレクトすると同時に、バリデーションエラーメッセージをセッションに一時的に格納してくれます。これは、テンプレート変数$errorsでアクセスできます。入力画面では、このテンプレート変数を使って、該当メッセージを取り出して表示するコードを記載しておく必要があります。これが、リスト5になります。

[リスト5]resources/views/chap8/input.blade.php
〜省略〜
<h1>入力画面</h1>
@if($errors->any())  // (1)
<section style="border: 1px red solid">
	<ul style="color: red">
	@foreach($errors->all() as $error)  // (2)
		<li>{{$error}}</li>
	@endforeach
	</ul>
</section>
@endif
<form action="/firstlaravel/public/chap8/addData" method="post">
〜省略〜

 ここでは、h1タグとformタグの間にバリデーションメッセージを表示する領域としてsectionタグを配置しています。そしてバリデーションメッセージの有無で、このタグの部分全体の表示/非表示を切り替えています。その際、有効なのが(1)のany()メソッドです。

 また、各々のメッセージは(2)のようにall()メソッドで取り出した配列をループさせることで取り出せます。

 リスト5のコードを追記する前では、バリデーションエラーで戻ってきた際の画面が図1と同じ画面だったのに対し、追記した後では、図6のようにメッセージが表示されるようになります。

図6: バリデーションメッセージが表示された入力画面

図6: バリデーションメッセージが表示された入力画面

 なお、このバリデーションメッセージはあくまで一時的にセッションに格納されているため、一度表示された瞬間にセッションから消えてしまいます(このような仕組みを「フラッシュメッセージ」といいます)。つまり、バリデーションメッセージが表示されるのは、バリデーションエラーが生じてリダイレクトされた時のみで、もう一度入力画面を表示させると、図1のようにメッセージのない入力画面となってしまいます。

個別のバリデーションメッセージ表示は@errorディレクティブ

 図6、つまりリスト5のコードでは、バリデーションメッセージをまとめて表示させるような画面構成でした。これを、各入力欄の下に表示させるように、個別でバリデーションメッセージを表示させたい場合は、次のように@errorディレクティブを利用し、引数としてname属性を渡します。

<label for="height">
	身長: 
	<input type="text" name="height" id="height">
</label>
@error("height")
<p>{{$message}}</p>
@enderror

 各々のバリデーションメッセージは$messageテンプレート変数で表示できます。

バリデーションメッセージのカスタマイズ

 これで無事バリデーションを実装できるようになりましたが、図6を見てもわかるようにメッセージが英語のままです。これを日本語化するなど、メッセージをカスタマイズするにはどうすればいいのでしょうか。一番簡単なのは、これらバリデーションメッセージがまとめて記述されたresources/lang/en/validation.phpファイルがあるので、それを利用する方法です。このファイルパスにenとついていることからわかるように、これは英語用のメッセージファイルです。これを日本語化するには、resources/lang/に日本語を表すjaフォルダを作成し、同名のファイルを作成します。といっても、いちいち記述するのは面倒ですので、resources/lang/jaフォルダ内にvalidation.phpをコピーし、リスト6のように必要部分を書き換えることにしましょう。

[リスト6]resources/lang/ja/validation.php
<?php
return [
	〜省略〜
	"numeric" => ":attribute は数値で入力してください。",  // (1)
	〜省略〜
	"required" => ":attribute の入力は必須です。",  // (2)
	〜省略〜
	"attributes" => [  // (3)
		"name" => "名前",  // (4)
		"height" => "身長",  // (4)
		"weight" => "体重"  // (4)
	],
];

 returnに続く連想配列に、バリデーションルール名がずらりと並んでいます。これらはアルファベット順になっていますので、numericとrequiredはすぐに見つかると思います。それを、リスト6の(1)や(2)のように書き換えてください。

 ここで、:attributeがそのまま残っていますが、実は、この:attributeの部分にname属性値がそのまま挿入されるようになっています。するとバリデーションメッセージは、例えば次のように表示されてしまいます。

height の入力は必須です。

 そこで、この:attributeの部分に独自の文字列を挿入できる仕組みがリスト6の(3)の部分です。オリジナルのvalidation.phpでは[]と空の連想配列となっていますが、ここに(4)のように、name属性値に対応する文字列を記述していきます。こうすることで、:attributeの部分にname属性値に応じて適切な文字列が挿入されるようになります。

 最後に、このjaフォルダ中のファイルが適用されるように、アプリケーション全体の言語設定を日本語に変更しておきましょう。config/app.phpファイル中の次の部分を変更します。

'locale' => 'en',

 これを、次のように日本語設定に変更してください。

'locale' => 'ja',

 その上で、もう一度動作確認した画面が図7です。

図7: バリデーションメッセージが日本語化された入力画面

図7: バリデーションメッセージが日本語化された入力画面

 無事、バリデーションメッセージが日本語化されています。

まとめ

 今回は、入力チェックをLaravelに任せるバリデーション機能を紹介しました。

 次回は、Laravelでデータベースを利用する方法を紹介します。

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
人気のPHPフレームワークLaravelを習得しよう連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS Twitter: @yyamada(公式)、@yyamada/wings(メンバーリスト) Facebook<個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるReact実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/12329 2020/06/05 11:00

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング