はじめに
この記事はLaravelでAPIを操作する際のエラーハンドリングとバリデーションに関する手順をまとめたメモになります
ルーティングの設定
routes/api.php
に、APIのルートを追加することで、基本的なPOSTリクエストを受け取るAPIを設定します。
Route::post('/user', [UserController::class, 'store']);
コントローラーの作成
以下のコマンドでコントローラーを生成することができます
php artisan make:controller UserController
コントローラーに必要なメソッド(例)
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class UserController extends Controller
{
public function store(Request $request)
{
// バリデーション処理
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:8',
]);
// 正常処理
return response()->json(['message' => 'User created successfully']);
}
}
マスアサインメントの設定
マスアサインメントとは
特定の作業やリソース(人、物、情報など)を一度に多くの対象に割り当てることを指します。
例えば、学校のイベントで多くの生徒が役割を持つ場合、一斉に役割を振り分けることがマスアサインメント
です。
Laravelのマスアサインメント
この記事では一度に複数のデータを連想配列としてモデルに渡し、その全てを一括で保存すること
をマスアサインメントと呼称しております
Laravelではセキュリティのために、マスアサインメントで保存する際には制限が設けられており、この制限によってマスアサインメントが許可されていないフィールドに対して一括でデータを保存しようとする
と、システムはマスアサインメントによる不正な操作と判断し、エラーを発生させます
マスアサインメントの例
以下の例では保存処理で 'name', 'email', 'password'を新規保存する際にバリデーションの対象となっていたのでマスアサインメントの設定
を実施しています
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
// マスアサインメントを許可するフィールドを指定
protected $fillable = ['name', 'email', 'password'];
}
バリデーションの方法と概要
バリデーションとは、入力されたデータが正しいかどうかを確認することです。
例えば、ウェブサイトのフォームに情報を入力するときに、その情報が適切かどうかをチェックするために使われます。これにより、間違ったデータや不完全な情報が送信されるのを防ぎます。
バリデーションの例
$validated = $request->validate([
'name' => 'required|string|max:255',
'email' => 'required|email|max:255|unique:users',
'password' => 'required|min:8',
]);
- name フィールドに対して
必須
文字列
最大255文字
という3つのルールを適用する場合は上記のように書きます - リクエストの中身が
required
,string
,max:255
の3つのルールを満たさない場合はエラーを発生させます
メソッドの補足
- $request->validate()
リクエストから送信されたデータ($request)に対してバリデーションを行います。データが正しくない場合は、自動的にエラーレスポンスが返されます
- $request
クライアントから送信されたデータを含むオブジェクトです
- validate()
リクエストのデータがルールに従っているかどうかを検証します
バリデーションの種類について
Laravelで設定できるバリデーションルール以下の通り様々存在します
必須/オプション
- accepted: フィールドが yes, on, 1, または true であることを確認
- active_url: フィールドが有効なURLであることを確認
- after:date : フィールドが指定された日付より後の日付であることを確認
- after_or_equal:date : フィールドが指定された日付以上であることを確認
- alpha: フィールドがアルファベットのみであることを確認
- alpha_dash: アルファベット、数字、ダッシュ、アンダースコアのみであることを確認
- alpha_num: アルファベットと数字のみであることを確認
- array: フィールドが配列であることを確認
- bail: 最初のバリデーションエラーが発生したら、後続のルールをスキップ
数値/長さ
- between:min,max: 数値、文字列、またはファイルのサイズが指定された範囲内であることを確認
- boolean: フィールドが true または false であることを確認
- confirmed: 指定されたフィールド(通常はパスワード)が確認フィールドと一致することを確認
- date: フィールドが有効な日付であることを確認
- date_equals:date : 指定された日付と等しいことを確認
- date_format:format: フィールドが指定されたフォーマットと一致することを確認
ファイル
file: フィールドがアップロードされたファイルであることを確認
image: 画像ファイルであることを確認(jpeg, png, bmp, gif, svg, webp)
mimes:types: ファイルが指定されたMIMEタイプ(例: jpeg, png)であることを確認
mimetypes:types: ファイルが指定されたMIMEタイプ(例: image/jpeg, video/mp4)であることを確認
比較
- different:field: 他のフィールドと異なることを確認
- digits:value: 指定された桁数であることを確認
- digits_between:min,max: 指定された範囲内の桁数であることを確認
- email: フィールドが有効なメールアドレス形式であることを確認
- exists:table,column: データベースの指定されたテーブルとカラムに値が存在することを確認
ユニーク性
- unique:table,column: 指定されたテーブルのカラムにおいて値がユニークであることを確認
サイズ/範囲
- max:value : フィールドが指定された最大サイズ(文字数やファイルサイズなど)以下であることを確認
- min:value : フィールドが指定された最小サイズ以上であることを確認
その他
- nullable: フィールドが空でも許容することを指定
- regex:pattern: フィールドが指定された正規表現パターンに一致することを確認
- required: フィールドが必須であることを確認
- required_if:anotherfield,value: 指定されたフィールドが特定の値の場合に、このフィールドが必須であることを確認
- required_with:field1,field2,...: 指定された他のフィールドが存在する場合、このフィールドが必須であることを確認
Laravelのエラーハンドリング
バリデーションなどによってエラーが発生した場合にエラーを適切に処理するための仕組みをエラーハンドリングと呼びます。
エラーハンドリングをすることで、ユーザーに対して理解しやすいエラーメッセージを表示したり、ログにエラー情報を記録したりすることができます。
エラーハンドリングの流れ
バリデーションによるエラーなどが発生した場合、以下の流れでエラー処理が実行されます
① エラーオブジェクトがスローされる
- 「スロー」するとは「投げる」という意味合いで、例えばバリデーションエラーの場合が発生した場合は
controller
でValidationException
というエラーオブジェクトが生成されます。そのオブジェクトはLaravelのフレームワークによって自動的にキャッチされ、Handler.php
に渡されます - ValidationExceptionはバリデーションルールに従わない入力があった場合にcontrollerで作成されるエラー情報が格納されたオブジェクトです
- ログインをしていないユーザーがログイン後のページを見ようとした時に発生する
AuthorizationException
などエラーの種類によってエラーオブジェクトは複数存在し、Handler.phpへスローされます
② Handler.phpの呼び出し
Handler.phpではエラーが発生した際の処理全般が定義されており、生成されたエラーオブジェクトをIF文などで判断し実行される処理を区別できます。
③ renderメソッドの実行
Handler.phpにはrenderメソッドが存在し、スローされたエラーオブジェクトが引数として渡されます。このメソッド内では、エラーオブジェクトが$exceptionという変数に代入され、if文などを使ってエラーオブジェクトの種類に応じた特定の処理(例えば、エラーページの表示や適切なレスポンスの生成)を行うことができます。
Handler.phpについて
Laravelのアプリケーション内でエラーや例外が発生した場合、上述の通りapp/Exceptions/Handler.php
が呼び出されその情報は $exception
という変数に格納されます
namespace App\Exceptions;
use Exception;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
class Handler extends ExceptionHandler
{
// エラーを記録する
public function report(Throwable $exception)
{
// エラーの情報を記録します
parent::report($exception);
}
// エラーメッセージを返す
public function render($request, Throwable $exception)
{
// 特定のエラーに対してカスタムメッセージを返す
if ($exception instanceof CustomException) {
return response()->json(['error' => 'カスタムエラーメッセージ'], 400);
}
// デフォルトのエラーメッセージを返す
return parent::render($request, $exception);
}
}
-
parent::report($exception);
Laravelがエラーや問題が起こったときに、そのエラーの情報を自動で記録してくれる機能を呼び出すためのものです。削除した場合はLaravelの標準のエラーログ(storage/logs/laravel.log に保存)は行われません。 -
if ($exception instanceof CustomException)
$exception という変数に入っているエラーが、CustomException という特定のエラー(例外)であるかどうかを確認する」ためのコードです。 -
return response()->json()
response() は、Laravelのヘルパー関数で、HTTPレスポンス(サーバーからクライアントへの応答)を作成するためのものです。json() は、レスポンスをJSON形式に変換します。APIでは、データをやり取りするときにJSON形式がよく使われます -
json(['error' => 'カスタムエラーメッセージ'], 400)
'error' というキーに対して 'カスタムエラーメッセージ' という内容が設定されています。このメッセージはGoogle Chromeの検証ツールからレスポンスなどで確認できます。同時にHTTPステータスコード(400)
が返されます。HTTPステータスの番号およびメッセージの内容は自由に変更できます
エラーページに誘導させる
エラーが発生した際に特定のエラーページへ自動でリダイレクトさせたい場合は、以下のようにエラーページへリダイレクトさせます
public function render($request, Throwable $exception)
{
// 401エラー(未認証)
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException) {
return redirect('/401'); // 401ページにリダイレクト
}
// 403エラー(アクセス拒否)
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException) {
return redirect('/403'); // 403ページにリダイレクト
}
// 404エラー(ページが見つからない)
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\NotFoundHttpException) {
return redirect('/404'); // 404ページにリダイレクト
}
// 500エラー(サーバー内部のエラー)
if ($exception instanceof \Symfony\Component\HttpKernel\Exception\HttpException) {
return redirect('/500'); // 500ページにリダイレクト
}
// その他のエラーについては、標準のエラーメッセージおよびページを表示
return parent::render($request, $exception);
}
HTTPステータスについての補足(エラーコード)
- 401エラー
認証が必要なページにアクセスした際にリダイレクトされます - 403エラー
アクセスが拒否された場合、403エラーページにリダイレクトされます - 404エラー
指定されたページが見つからない場合、404エラーページにリダイレクトされます - 500エラー
サーバーで何らかの問題が発生した場合、500エラーページにリダイレクトされます - その他のエラー
上記の条件に該当しないエラーが発生した場合、Laravelのデフォルトのエラーハンドリングが行われます。