🏃‍♂️Reducer Resources

Introduction

Laravel Resource Reducer is the SuperSet from Laravel Resource, thus we can use the Reducer just like the way we use normal Resource.

Create a Reducer Resource

Create a resource then change the extends to ShipSaasReducer\Json\JsonReducerResource

namespace App\Http\Resources;

use ShipSaasReducer\Json\JsonReducerResource;

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,
        ];
    }
}

Remember to wrap your fields/getters in a Closure/Callable.

  • This ensures computation won't start until the right time 😉.

When migrating from Resource to Reducer, simply migrate your Resource class by extending ShipSaasReducer\Json\JsonReducerResource, implement the definitions method.

The migration is 1:1 update with no breaking changes 😉.

Relationships

To declare a relationship in definition, simply use the ::makeRelation method.

By declaring the relationship, Resource Reducer would be able to automatically do the eager-loading.

E.g.: User has one Role and has many Articles

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'),
            'articles' => ArticleResource::makeRelation('articles'),
        ];
    }
}

The required param of makeRelation is the Eloquent's relationship method name.

With the above example, our User model has 2 methods:

  • public function role(): BelongsTo

  • public function articles(): HasMany

You mustn't wrap the relationship declaration in the Closure

Managing eager loading is super freaking hard, everybody knows that. Especially when working with normal Laravel Resources, you have to do the with() or load() in the Controller/Service before passing into the Resource.

No more pain, Reducer ensures your relationship(s) will be loaded based on your need, keep the N+1 problems out of your mind, and build great performance apps.

Return data to Consumer

For single model

public function show(User $user): JsonResponse
{
    return (new UserResource($user))->response();
}

For normal listing

public function index(): JsonResponse
{
    $users = User::limit(10)->get();
    return UserResource::collection($users)->response();
}

For pagination

public function index(): JsonResponse
{
    $users = User::paginate(10);
    return UserResource::collection($users)->response();
}

There are some issues when using new UserResource($paginatedUser) so you need to use the collection for now.

We'll let you know once it's compatible.

Last updated