The Best Way to Handle Api Response in Laravel[php]
Tags: laravel, php, api
Published: 2023-08-10 07:25:00

In the world of software development, ensuring smooth communication between different parts of a system is crucial. One of the aspects that greatly influences this communication is the format in which an application's API (Application Programming Interface) responds to requests. A well-defined and consistent API response format not only enhances interoperability but also simplifies debugging, error handling, and collaboration among development teams.

In this blog post, we'll explore the importance of having a standard API response format and specifically delve into why using status codes like 200 for success and 400 for error.

**Unstructured Api**
Unstructured API responses are not well-defined and can be difficult to consume. They can also be inconsistent, which can make it difficult to develop applications that rely on them. For example, In the image below, an array of objects is returned from an endpoint.


![Unstructured api response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r0r5nsp4p5af5v248rfs.png)

**The Role of a Standard API Response Format**
An API response format serves as a contract between the server and the client. In the pursuit of clarity and simplicity, many modern APIs have embraced a streamlined approach to status codes. This approach involves using just two distinct status codes: 200 and 400. Let's explore how this simplicity brings forth a host of benefits:

1. Clear Communication: The use of two status codes conveys a clear and straightforward message to both developers and clients. A status code of 200 indicates a successful request, while a status code of 400 signals an error. This simplicity eliminates ambiguity and promotes quick understanding.

2. Efficient Debugging: When errors occur, having a binary division between success and error reduces the complexity of error analysis. Developers can instantly recognize whether the issue lies in the client's request (status code 400) or if the request was successfully processed (status code 200).

3. Consistency in Handling: With only two types of status codes to manage, error handling becomes consistent across different endpoints and methods. Developers can apply a standardized approach to error responses, making the codebase cleaner and more maintainable.

4. Simplified Documentation: Fewer status codes mean less documentation overhead. Developers and integrators can quickly grasp the meaning behind the status codes, resulting in less time spent deciphering documentation.

**Building A Structured Api Response Format**
Let's take a look at how a standardized API response format can be practically implemented in Laravel.

```php
<?php

namespace App\Enum;

enum ResponseCodeEnums: int {

    //-- Codes starting with number 3 represents Album related codes--//
    case ALL_ALBUM = 3000;
    case ALBUM_CREATED = 3001;
    case SHOW_SINGLE_ALBUM = 3002;
    case NO_ALBUM_CONTENT = 3004;
    case UPDATE_SINGLE_ALBUM = 3005;
    case ABLUM_CONFLICT = 3009;
    case CREATE_ALBUM_REQUEST_VALIDATION_ERROR = 3003;
    case DELETE_ALBUM = 3014;

    public function toString(): object
    {
        return match ($this) {
            self::ALBUM_CREATED => (object)['status' => 200, 'response_code' => $this, 'message' => $this->name],
            self::ALL_ALBUM => (object)['status' => 200, 'response_code' => $this, 'message' => $this->name],
            self::SHOW_SINGLE_ALBUM => (object)['status' => 200, 'response_code' => $this, 'message' => $this->name],
            self::NO_ALBUM_CONTENT => (object)['status' => 200, 'response_code' => $this, 'message' => $this->name],
            self::UPDATE_SINGLE_ALBUM => (object)['status' => 200, 'response_code' => $this, 'message' => $this->name],
            self::DELETE_ALBUM => (object)['status' => 200, 'response_code' => $this, 'message' => $this->name],
            self::ABLUM_CONFLICT => (object)['status' => 400, 'response_code' => $this, 'message' => $this->name],
            self::CREATE_ALBUM_REQUEST_VALIDATION_ERROR => (object)['status' => 400, 'response_code' => $this , 'message' => $this->name],
        };
    }
}
```

In this example, the custom error codes (ABLUM_CONFLICT and CREATE_ALBUM_REQUEST_VALIDATION_ERROR) are associated with a 400 status code, indicating client errors. These codes can provide detailed insights into the nature of the error while maintaining a consistent structure.

**Simplicity Meets Customization: A Development Paradigm**
Simplicity and customization intertwine to create a development paradigm that emphasizes clarity and efficiency. By embracing this approach, development teams can streamline error handling, bolster debugging capabilities, and establish an environment conducive to seamless collaboration.
For example, I can use this Response code Enums in when building my controllers to return my response.

```php
public function store(StoreAlbumRequest $request)
    {
        $name = $request['name'];

        //-- Check if an album with the same name already exists --//
        $existingAlbum = Album::where('name', $name)->first();
        if ($existingAlbum) {
            return $this->sendResponse($existingAlbum, ResponseCodeEnums::ABLUM_CONFLICT->toString());
        }

        $album = Album::create($request->all());
        return $this->sendResponse($album, ResponseCodeEnums::ALBUM_CREATED->toString());
    }
```

In the store controller action above, you will observe the sendResponse method receives two argument: Data and the response code object. Let's take a peep of what the method looks like.

```php
<?php

namespace App\Traits;

trait ApiResponseTrait
{
    public function sendResponse($data, $responseCodeObject)
    {
        $statusCode = $responseCodeObject->status;
        $responseCode = $responseCodeObject->response_code;
        $responseMessage = $responseCodeObject->message;

        return response()->json([
            'status' => $statusCode,
            'response_code' => $responseCode,
            'message' => $responseMessage,
            'data' => $data,
        ], $statusCode);
    }
}
```

To quickly summarize what is going on, the sendResponse method allows us format our json response in a consistent manner, such that we only have to write it once and call it anywhere in our application by passing the data we want the client to receive and also the response code object which we built. 

By applying the simple sendResponse method, we are able to format our api response neatly as shown in the image below


![Structured api response](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/eelsqjct90kaxhvamh20.png)

**In Conclusion**
A standardized API response format stands as a pillar of effective communication in software development. The fusion of two distinct status codes - 200 for success and 400 for errors - brings clarity and efficiency to API interactions. This streamlined approach simplifies error handling, promotes consistent development practices, and ultimately fosters harmonious collaboration among development teams.

The integration of custom response codes elevates the sophistication of API responses, providing an extra layer of clarity and precision. With this holistic approach, API responses transcend technicalities to become tools that empower developers to communicate effectively and construct robust, user-centric applications.