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から(検証時ではなく)ランタイムエラーを返すより良い方法はありますか?
以下のように、json応答にステータスコードを設定できます。
return Response::json(['error' => 'Error msg'], 404); // Status code here
または、ヘルパー関数を使用するだけで:
return response()->json(['error' => 'Error msg'], 404); // Status code here
多くの方法でそれを行うことができます。
まず、ステータスコードを提供することで、簡単な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エラーを返します。