# 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`

<pre class="language-php"><code class="lang-php">namespace App\Http\Resources;

<strong>use ShipSaasReducer\Json\JsonReducerResource;
</strong>
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,
        ];
    }
}
</code></pre>

Remember to **wrap** your fields/getters in a **Closure/Callable**.&#x20;

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

{% hint style="info" %}
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 😉.
{% endhint %}

### Relationships

To declare a relationship in definition, simply use the `::makeRelation` method.&#x20;

> 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

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

{% hint style="info" %}
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
  {% endhint %}

{% hint style="warning" %}
You mustn't wrap the relationship declaration in the Closure
{% endhint %}

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

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

#### For normal listing

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

#### For pagination

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

{% hint style="warning" %}
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.
{% endhint %}
