2

I want to know which is the way to implement error in RestAPI, actually if a method in my classes generate an exception I return this ...

if(mysqli_connect_errno()) {
     throw new Exception("Can't connect to db.");
}

... but this is a bad practice 'cause an API should be return a json.

So my idea is create a class called Errors and, in each class, when an error is fired I simply call the relative error number for display the json error.

Someone have another idea?

4
  • 1
    you could use try catch block to grab the exceptions and then output in json format Commented Feb 16, 2016 at 12:49
  • @Richie, well this is the easy way of course. It's not better create an error class with default error? Commented Feb 16, 2016 at 12:50
  • 1
    i think printing your error as JSON actually is the best way to go - if you create your own class or catch exceptions is up to taste. I would use a combination of both, while using exceptions only for truly exceptional errors - but in the end the client's gonna know if everything went wrong, either by receiving a JSON-formatted error or by receiving no JSON at all. Commented Feb 16, 2016 at 12:52
  • You could make exceptions for BadRequestException, ServerErrorException, ForbiddenException etc., and have an exception handler manage the HTTP code you're returning. Commented Feb 16, 2016 at 13:07

4 Answers 4

5

I think @Gwendal answer is good but it's no enough just to return a json response, you also have to return the proper http code:

<?php

try {
    // Do your stuff        
} catch (Exception $e) {
    header($_SERVER['SERVER_PROTOCOL'] . ' 500 Internal Server Error', true, 500);
    echo json_encode(array("success" => false, "message" => $e->getMessage()));
    return;
}
Sign up to request clarification or add additional context in comments.

1 Comment

and this is how an REST API should be implemented.
3

Maybe something like so :

<?php

try {
    // Do your stuff
    if(mysqli_connect_errno()) {
        throw new Exception("Can't connect to db.");
    }
} catch (Exception $e) {
    echo json_encode(array("success" => false, "message" => $e->getMessage()));
    return;
}

3 Comments

the problem is that in the response (for example) I get this=> Warning mysqli_connect(): Unknow database x and later I get: {"success":false, "message: etc.... I want print the json only.
@SevengamesXoom Just remove error_reporting, I think its the only way
@Gwendal You can use the error suppression operator and check the result with error_get_last.
3

I think you're in the right path. There are a couple of concerns that you're dealing with in here. First one is error handling, whilst the second one is error formatting.

Error handling can be done in several ways, and throwing exceptions is one of them. In order to find out when something bad happened, you'll need to wrap your exceptions within a try/catch block:

try {
    //logic
    if(mysqli_connect_errno()) {
        throw new Exception("Can't connect to db.");
    }
    //more logic
} catch (Exception $e) {
    //handle the error here
}

If you're following this route, I'd suggest you to be more specific in your exceptions, so you can better build your responses in your API. It's not the same having the DB down than to not being able to find a resource, for instance:

try {
    //logic
    if(mysqli_connect_errno()) {
        throw new DBException("Can't connect to db.");
    }

    if(is_null($entity)) {
        throw new ResourceNotFoundException("Entity could not be found");
    }
    //more logic
} catch (DBException $e) {
    //handle DB error here
} catch (ResourceNotFoundException $e) {
    //handle resource not found error here
}

Now for the formatting part, the normal response in REST APIs are JSON responses. One way to go about it, would be to create a specific class whose sole responsibility would be to transforms your response into a valid JSON:

...
} catch (DBException $e) {
    return $this->JSONResponse->format("Sorry we could not complete your request", 500);
} catch (ResourceNotFoundException $e) {
    return $this->JSONResponse->format("The resource you were looking for could not be found", 404);
}

As you can see, different errors have different status codes. The implementation of the class is quite trivial:

class JSONResponse {
    public function format($message, $statusCode) {
         return json_encode(['message' => $message, 'code' => $statusCode]);
    }
}

This does not change the status code of the response though, which is essential to good REST API design. You'll need to set the appropriate status code by using this function.

You can find a more robust and flexible implementation of this class in the Symfony HTTPFoundation Component, which extends from the normal Response class.

Comments

0

My RESTful API always returns a JSON of this structure:

[
    'resource' : [],

    'code'     : [
        'id'   : int,
        'msg'  : string
    ],

    'meta'     : [],

    'log'      : []
]

If I return data, the data is always in resource and code['id'] is always 0 (which represents 'OK'). When an error occours, I return an empty resource and some error code. Also I provide some extra information via meta and can log some actions via log which helps me a lot with debugging.

This might also help you with future issues, for example if you want to split an answer into pages so the client should request data via GET /path/to/resource/page/:page or want to notice the client that a certain request path is deprecated.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.