⭐️ Optimizes your response using Laravel Resource Reducer
Tags: php, laravel, opensource, api
Published: 2023-09-24 02:34:40

Hey guys,

I'm delighted to share my latest work on the performance of your Laravel API endpoints 😉.

Check out: [Laravel Resource Reducer](https://github.com/shipsaas/laravel-resource-reducer) 😎

Before delving into Laravel Resource Reducer, it's essential to understand the drawbacks of the existing Laravel Resource 👀.

## Laravel Resource

I assume that you all are already familiar with Laravel Resource, aren't you? If not, you can explore it here: https://laravel.com/docs/10.x/eloquent-resources

Simplest tl;dr:

> Laravel Resource is a layer to compute your Eloquents into the Responses

### Problems

Let's say, we have an endpoint `v1/users` which returns an array of users:

```php
[
    'data' => [
        [
            'id' => 1,
            'name' => 'Seth Phat',
            'email' => 'me@sethphat.com',
            'created_at' => '2023-01-01',
            'role' => 'ADMIN',
            'avatar_url' => '...',
        ],
        [
            // ... user 2,
        ],
        // ... more
    ],
]
```

Everything is suitable for the listing page, such as rendering users in the table.

However, if we want to use a dropdown of users on another page (for example, to assign a user as a reviewer), then, you won't need all the returned fields, you only need: id & name (or additionally, email)

=> The CONs while reusing the above endpoint:

- Redundant fields returned 🥲
- Slower response 🥲
- You will end up creating a new endpoint just for the dropdown 🥲 Development takes more time & the team has to maintain more 🥲

Moreover, if you have relationship(s) defined in your `UserResource` and you wish to bulk them up in the response, then you will need to do eager-loading before transforming `UserResource`, thus you'll have these CONs:

- Always need to do the eager-loading in the outer layer 🥲
    - And maintain that 🥲
- **n*n** response size because it bulked up with enormous data 🥲
- Definitely: slower response 🥲

Now that you know the current problems. Let's jump into the super solution 😎

## Meets Laravel Resource Reducer

Laravel Resource Reducer helps you to optimize every API request by:

- Reduce the response's size, get what you need ⭐️
- Responses to API consumers faster 🚀
- Computation only starts when required, save CPU & memory 😎
- Built-in relationship access by using dot notation 👀
- Eager-loading on steroids (automated eager-loading, no more N+1 pain) 🔋

A simple yet super effective method to skyrocketing your API responding times 🥰

> If you know about GraphQL, To query for data, we need to define which fields we want to retrieve. Laravel Resource Reducer is heavily inspired from GraphQL approach. ❤️

### Usage (from API Consumer)
Let's say, we have this endpoint: `v1/users` which returns `User[]`

`User` has these fields: id, name, email, avatar_url, created_at, role (relationship)

Simply add `_f[]` or `_fields[]` query param

- Get `id`, `name`:
    - https://my-api.com/v1/users?_fields[]=id&_fields[]=name
- Get `id`, `email`, and the role name (relationship)
    - https://my-api.com/v1/users?_f=id,email,role.name

Isn't it awesome? 😎

### Implementation

#### Resource Reducer

```php
class UserResource extends JsonReducerResource
{
    public function definitions(Request $request): array
    {
        return [
            'id' => fn () => $this->id,
            'email' => fn () => $this->email,
            'created_at' => fn () => $this->created_at,
            'role' => RoleResource::makeRelation('role'),
        ];
    }
}
```

Remember to wrap your fields with in closures, to defer execution 😎

#### Return responses

```php
// UserController@index
return UserResource::collection($users)->response();

// UserController@show
return (new UserResource($user))->response();
```

The usage is as same as Laravel Resource 😉


## Final words

If this package is helpful, please give it a ⭐️⭐️⭐️.

Consider using Laravel Resource Reducer to optimize & skyrocket your API endpoints 💪

Thank you and have a great day!