web-dev-qa-db-fra.com

Comment faire en sorte que Laravel retourne une erreur personnalisée pour un JSON REST API

Je développe une sorte d'API RESTful. Quand une erreur survient, je lance une erreur App::abort($code, $message)

Le problème est le suivant: je veux qu’il jette un tableau formé par JSON avec les clés "code" et "message", chacune contenant les données susmentionnées. 

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

Est-ce que quelqu'un sait si c'est possible, et si c'est le cas, comment je le fais?

24
Dennis Braga

allez dans votre app/start/global.php.

Ceci convertira toutes les erreurs pour 401 et 404 en une erreur json personnalisée au lieu du stackops de Whoops. Ajoute ça:

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);        
    }

});

C'est l'une des nombreuses options permettant de gérer ces erreurs. 


Pour créer une API, il est préférable de créer votre propre aide, telle que Responser::error(400, 'damn'), qui étend la classe Response.

Un peu comme:

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);
}
38
majidarif

Vous pouvez transmettre un tableau à la réponse JSON renvoyée:

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

Voici ce que j'utilise (Laravel 5.2):

Selon: https://laravel.com/docs/5.2/errors , nous pouvons spécifier une fonction de rendu personnalisée pour les erreurs dans app\Exceptions\Handler.php. Tout ce que j'ai fait était de changer ma fonction de rendu en ceci:

    /**
     * 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;
    }

Après cela, vous devez simplement vous assurer que toutes vos demandes d'API spécifient l'en-tête Accept: application/json. J'espère que cela t'aides :)

16
Ibrahim Lawal

Selon la réponse d'Ibrahim, toutes les demandes ajax ne veulent pas du JSON. Répondre au "code d'état" et le "statut" est inutile car elles signifient la même chose. Plus que cela, il n'est pas nécessaire de mentionner dans la réponse "statut" du tout, puisque le code de réponse "dit" cela. Quelque chose comme ça devrait fonctionner parfaitement:

/**
 * 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

Dans Laravel5.6, je spécifie généralement une fonction de rendu personnalisée pour les erreurs dans app\Exceptions\Handler.php. Tout ce que j'ai fait était de changer ma fonction de rendu en ceci:

/**
 * 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