• 7
name

A PHP Error was encountered

Severity: Notice

Message: Undefined index: userid

Filename: views/question.php

Line Number: 191

Backtrace:

File: /home/prodcxja/public_html/questions/application/views/question.php
Line: 191
Function: _error_handler

File: /home/prodcxja/public_html/questions/application/controllers/Questions.php
Line: 433
Function: view

File: /home/prodcxja/public_html/questions/index.php
Line: 315
Function: require_once

I'm developing some kind of RESTful API. When some error occurs, I throw an App::abort($code, $message) error.

The problem is: I want him to throw a json formed array with keys "code" and "message", each one containing the above mentioned data.

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

Does any one knows if it's possible, and if it is, how I do it?

go to your app/start/global.php.

This will convert all errors for 401 and 404 to a custom json error instead of the Whoops stacktrace. Add this:

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

});

This is one of many options to handle this errors.


Making an API it is best to create your own helper like Responser::error(400, 'damn') that extends the Response class.

Somewhat like:

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);
}
  • 49
Reply Report
      • 2
    • I really liked the second thing you said. About the API, though I didn't understand it entirely. Should I create another class, where I extends Response class and call it instead of the "right" one? It's that it?

You can pass an array to the returned JSON response:

$returnData = array(
    'status' => 'error',
    'message' => 'An error occurred!'
);
return Response::json($returnData, 500);
  • 34
Reply Report

Here is what I use (Laravel 5.2):

According to: https://laravel.com/docs/5.2/errors , we can specify a custom render function for errors in app\Exceptions\Handler.php. All I did was to change my render function to this:

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

After this, all you need do is make sure all your API requests specify the Accept: application/json header. Hope this helps :)

  • 19
Reply Report

According to Ibrahim's answer, not every ajax request wants JSON, Responding the "status code" and the "status" is unnecessary since they both mean the same thing. More than that, there's no need to mention in the response "status" at all, since the response code "says" that. Something like that should work perfectly:

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

Laravel 6:

You simply have to set Accept:application/json header in your API request from client-side and Laravel will automatically return a JSON format error.

Example:

{

"message": "Unauthenticated."

}

  • 2
Reply Report

In Laravel5.6, I usually specify a custom render function for errors in app\Exceptions\Handler.php. All I did was to change my render function to this:

/**
 * 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
Reply Report
      • 2
    • That answer looke really good, but sadly it doesn't work for me, Laravel still gives me ```status "error" message "An error occurred."```` as response :(

Warm tip !!!

This article is reproduced from Stack Exchange / Stack Overflow, please click

Trending Tags

Related Questions