web-dev-qa-db-ja.com

どうすればLaravel JSONのカスタムエラーを返すREST API

何らかのRESTful APIを開発しています。エラーが発生すると、App::abort($code, $message)エラーをスローします。

問題は、「コード」と「メッセージ」のキーを持つJSON形式の配列をスローすることです。各キーには上記のデータが含まれています。

Array
(
    [code] => 401
    [message] => "Invalid User"
)

それが可能かどうか、そして可能であれば、私がそれを行う方法を知っている人はいますか?

27
Dennis Braga

_app/start/global.php_に移動します。

これは_401_および_404_のすべてのエラーをWhoopsスタックトレースではなくカスタムjsonエラーに変換します。これを追加:

_App::error(function(Exception $exception, $code)
{
    Log::error($exception);

    $message = $exception->getMessage();

    // switch statements provided in case you need to add
    // additional logic for specific error code.
    switch ($code) {
        case 401:
            return Response::json(array(
                    'code'      =>  401,
                    'message'   =>  $message
                ), 401);
        case 404:
            $message            = (!$message ? $message = 'the requested resource was not found' : $message);
            return Response::json(array(
                    'code'      =>  404,
                    'message'   =>  $message
                ), 404);        
    }

});
_

これは、このエラーを処理する多くのオプションの1つです。


APIを作成するには、Responseクラスを拡張するResponser::error(400, 'damn')のような独自のヘルパーを作成するのが最適です。

やや好き:

_public static function error($code = 400, $message = null)
{
    // check if $message is object and transforms it into an array
    if (is_object($message)) { $message = $message->toArray(); }

    switch ($code) {
        default:
            $code_message = 'error_occured';
            break;
    }

    $data = array(
            'code'      => $code,
            'message'   => $code_message,
            'data'      => $message
        );

    // return an error
    return Response::json($data, $code);
}
_
43
majidarif

返されたJSON応答に配列を渡すことができます。

$returnData = array(
    'status' => 'error',
    'message' => 'An error occurred!'
);
return Response::json($returnData, 500);
31
Philip

ここに私が使用するものがあります(Laravel 5.2):

https://laravel.com/docs/5.2/errors によると、app\Exceptions\Handler.phpでエラーのカスタムレンダリング関数を指定できます。私がしたことは、レンダリング関数をこれに変更することだけでした。

    /**
     * Render an exception into an HTTP response.
     * Updated to return json for a request that wantsJson 
     * i.e: specifies 
     *      Accept: application/json
     * in its header
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $e
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $e)
    {
        if ($request->ajax() || $request->wantsJson()) {
            return response()->json(
                          $this->getJsonMessage($e), 
                          $this->getExceptionHTTPStatusCode($e)
                        );
        }
        return parent::render($request, $e);
    }

    protected function getJsonMessage($e){
        // You may add in the code, but it's duplication
        return [
                  'status' => 'false',
                  'message' => $e->getMessage()
               ];
    }

    protected function getExceptionHTTPStatusCode($e){
        // Not all Exceptions have a http status code
        // We will give Error 500 if none found
        return method_exists($e, 'getStatusCode') ? 
                         $e->getStatusCode() : 500;
    }

この後、必要なことは、すべてのAPIリクエストがAccept: application/jsonヘッダーを指定していることを確認することだけです。お役に立てれば :)

16
Ibrahim Lawal

ビルトインvalidateメソッドと同じタイプの応答を返すために5.6で使用したものは次のとおりです。

response()->json(['errors' => ['email' => ['The email is invalid.']]], 422);

8
kjdion84

Ibrahimの答えによると、すべてのajaxリクエストがJSONを必要とするわけではありません。「ステータスコード」「ステータス」は両方とも同じことを意味するため、応答しません。それ以上に、応答コードは「言う」ので、応答で「ステータス」に言及する必要はまったくありません。そのようなものは完全に動作するはずです:

/**
 * Render an exception into an HTTP response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Exception  $e
 * @return \Illuminate\Http\Response
 */
public function render($request, Exception $e)
{
    if ($request->wantsJson())
        return response()->json(
            ['message' => $e->getMessage()],
            method_exists($e, 'getStatusCode') ? $e->getStatusCode() : 500);

    return parent::render($request, $e);
}
7
Eliya Cohen

Laravel5.6では、通常、app\Exceptions\Handler.php。私がしたことは、レンダリング関数をこれに変更することだけでした。

/**
 * Render an exception into an HTTP response.
 *
 * @param \Illuminate\Http\Request $request
 * @param \Exception               $e
 *
 * @return Response
 */
public function render($request, Exception $e)
{
    if ($request->wantsJson() && !($e instanceof ValidationException)) {
        $response = [
            'message' => (string)$e->getMessage(),
            'status_code' => 400,
        ];

        if ($e instanceof HttpException) {
            $response['message'] = Response::$statusTexts[$e->getStatusCode()];
            $response['status_code'] = $e->getStatusCode();
        } else if ($e instanceof ModelNotFoundException) {
            $response['message'] = Response::$statusTexts[Response::HTTP_NOT_FOUND];
            $response['status_code'] = Response::HTTP_NOT_FOUND;
        }

        if ($this->isDebugMode()) {
            $response['debug'] = [
                'exception' => get_class($e),
                'trace' => $e->getTrace()
            ];
        }

        return response()->json([
            'status'      => 'failed',
            'status_code' => $response['status_code'],
            'massage'     => $response['message'],
        ], $response['status_code']);
    }

    return parent::render($request, $e);
}
1
Sheng.Zh