web-dev-qa-db-ja.com

AJAXコントローラーからLaravelエラーを返す方法は?

REST 5でLaravel APIを構築しています。

Laravel 5では、_App\Http\Requests\Request_をサブクラス化して、特定のルートが処理される前に満たさなければならない検証ルールを定義できます。例えば:

_<?php

namespace App\Http\Requests;

use App\Http\Requests\Request;

class BookStoreRequest extends Request {

    public function authorize() {
        return true;
    }

    public function rules() {
        return [
            'title' => 'required',
            'author_id' => 'required'
        ];
    }
}
_

クライアントがAJAXリクエストを介して対応するルートをロードし、BookStoreRequestがリクエストがルールを満たさないと判断した場合、自動的にエラーをJSONオブジェクトとして返します。例えば:

_{
  "title": [
    "The title field is required."
  ]
}
_

ただし、Request::rules()メソッドは入力のみを検証できます。入力が有効であっても、要求が既に受け入れられてコントローラーに渡された後、他の種類のエラーが発生する可能性があります。たとえば、コントローラーが何らかの理由で新しいブック情報をファイルに書き込む必要があるが、ファイルを開くことができないとします。

_<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Http\Requests;
use App\Http\Controllers\Controller;

use App\Http\Requests\BookCreateRequest;

class BookController extends Controller {

    public function store( BookStoreRequest $request ) {

        $file = fopen( '/path/to/some/file.txt', 'a' );

        // test to make sure we got a good file handle
        if ( false === $file ) {
            // HOW CAN I RETURN AN ERROR FROM HERE?
        }

        fwrite( $file, 'book info goes here' );
        fclose( $file );

        // inform the browser of success
        return response()->json( true );

    }

}
_

明らかに、die()だけでもかまいませんが、それは非常にいです。検証エラーと同じ形式でエラーメッセージを返します。このような:

_{
  "myErrorKey": [
    "A filesystem error occurred on the server. Please contact your administrator."
  ]
}
_

独自のJSONオブジェクトを作成して返すことができますが、Laravelはこれをネイティブにサポートします。

これを行うための最良/最もクリーンな方法は何ですか?または、Laravel REST APIから(検証時ではなく)ランタイムエラーを返すより良い方法はありますか?

14
greenie2600

以下のように、json応答にステータスコードを設定できます。

return Response::json(['error' => 'Error msg'], 404); // Status code here

または、ヘルパー関数を使用するだけで:

return response()->json(['error' => 'Error msg'], 404); // Status code here
20
Jilson Thomas

多くの方法でそれを行うことができます。

まず、ステータスコードを提供することで、簡単なresponse()->json()を使用できます。

return response()->json( /** response **/, 401 );

または、すべてのエラーがjson応答であることを保証するより複雑な方法で、例外ハンドラーをセットアップして特別な例外をキャッチし、jsonを返すことができます。

開いた App\Exceptions\Handlerそして、以下を実行します。

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that should not be reported.
     *
     * @var array
     */
    protected $dontReport = [
        HttpException::class,
        HttpResponseException::class,
        ModelNotFoundException::class,
        NotFoundHttpException::class,
        // Don't report MyCustomException, it's only for returning son errors.
        MyCustomException::class
    ];

    public function render($request, Exception $e)
    {
        // This is a generic response. You can the check the logs for the exceptions
        $code = 500;
        $data = [
            "error" => "We couldn't hadle this request. Please contact support."
        ];

        if($e instanceof MyCustomException) {
            $code = $e->getStatusCode();
            $data = $e->getData();
        }

        return response()->json($data, $code);
    }
}

これは、アプリケーションでスローされた例外に対してjsonを返します。ここで、たとえばapp/ExceptionsにMyCustomExceptionを作成します。

class MyCustomException extends Exception {

    protected $data;
    protected $code;

    public static function error($data, $code = 500)
    {
        $e = new self;
        $e->setData($data);
        $e->setStatusCode($code);

        throw $e;
    }

    public function setStatusCode($code)
    {
        $this->code = $code;
    }

    public function setData($data)
    {
        $this->data = $data;
    }


    public function getStatusCode()
    {
        return $this->code;
    }

    public function getData()
    {
        return $this->data;
    }
}

MyCustomExceptionまたはMyCustomExceptionを拡張する任意の例外を使用して、jsonエラーを返すことができます。

public function store( BookStoreRequest $request ) {

    $file = fopen( '/path/to/some/file.txt', 'a' );

    // test to make sure we got a good file handle
    if ( false === $file ) {
        MyCustomException::error(['error' => 'could not open the file, check permissions.'], 403);

    }

    fwrite( $file, 'book info goes here' );
    fclose( $file );

    // inform the browser of success
    return response()->json( true );

}

現在、MyCustomExceptionを介してスローされる例外だけでなく、一般的にスローされるその他の例外もjsonエラーを返します。

6
Blue Genie