47
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

LaravelAdvent Calendar 2017

Day 19

Laravel でオレオレ例外処理を作成する

Last updated at Posted at 2017-12-18

はじめに

これは Laravel Advent Calendar 2017 19日目の記事です。

カスタム例外処理(クラス)の作成と使用方法について書いていきます。

例外処理というと難解そうですが、結構簡単な内容なのですぐ読み終わると思います。

環境

  • PHP: 7.1.5
  • Laravel: 5.5.24

前提

  • 今回は具体的な例として、バリデーションエラーの例外クラスを作成する
  • レスポンスは JSON 形式

作成手順

例外クラスを作成する

  • artisan コマンドで作成できる
  • php artisan make:exception ValidationException

作成した例外クラスを編集する

app/Exceptions/ValidationException.php
<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;

class ValidationException extends Exception
{
    public $request;
    public $message;

    public function __construct(Request $request, array $message)
    {
        $this->request = $request;
        // 複数のバリデーションエラー時には , で区切る
        $this->message = implode(',', $message);
    }

    public function report()
    {
        $xRequestId = array_key_exists('x-request-id', $this->request->header()) ? $this->request->header()['x-request-id'][0] : '';
        Log::info(
            $xRequestId,
            [
                'client_ip'      => $this->request->getClientIp(),
                'request_params' => $this->request->all(),
                'response_body'  => $this->message,
            ]
        );
    }

    public function render()
    {
        return response()->json(
            $this->message,
            422
        );
    }
}

解説

  • report() ではログとして表示させたい内容を設定している
  • render() ではレスポンスとして返したい内容を設定している

作成した例外クラスを呼ぶ

会員登録の Controller で呼び出してみる

app/Http/Controllers/Account/V1/RegisterController.php
<?php

namespace App\Http\Controllers\Account\V1;

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

class RegisterController extends Controller
{
    public function apply(Request $request)
    {
        $validation = \Validator::make(
            [
                'mail_to'        => $request->get('mail_to'),
                'register_token' => $request->get('register_token'),
            ],
            [
                'mail_to'        => 'required|email|max:128',
                'register_token' => 'required|alpha_num|size:64',
            ]
        );

        if ($validation->fails()) {
            throw new ValidationException($request, $validation->errors()->all());
        }
        
        ...
    }
}    

ルーティング

routes/account/v1.php
Route::put('registers/apply', 'Account\V1\RegisterController@apply');

例外を発生させてみる

不正なリクエスト

  • 必須パラメータである register token なし
curl -kv -X PUT -H "X-Request-Id: abc123" -d "mail_to=test@gmail.com" https://***-api.***.jp/account/v1/registers/apply

例外レスポンスの例

> 
* upload completely sent off: 37 out of 37 bytes
< HTTP/1.1 422 Unprocessable Entity
< Server: nginx/1.12.1
< Content-Type: application/json
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: no-cache, private
< Date: Mon, 11 Dec 2017 09:41:04 GMT
< X-RateLimit-Limit: 60
< X-RateLimit-Remaining: 57
< 
* Curl_http_done: called premature == 0
* Connection #0 to host ***-api.***.jp left intact
"The register token field is required."

解説

  • register token がリクエストパラメータに含まれていないため、The register token field is required. というようにエラーレスポンスを返している
  • ステータスコードも ValidationException で設定した 422 になっている

例外ログの例

[2017-12-11 09:41:04] local.INFO: test123 {"client_ip":"192.168.**.**","request_params":{"mail_to":"test@gmail.com"},"response_body":"The register token field is required."} 

おまけ

去年の Laravel Advent Calendar にも参加していたので良かったらどうぞ。

Laravel でカスタムバリデーションとそのテスト

47
46
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
47
46

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?