DEV Community

Yasser Elgammal
Yasser Elgammal

Posted on

How to make resources more reusable in Laravel

When working with Laravel API, we utilize resources to manage the process of returning collections in each response.

But, How can we do this with a single resource file to avoid messy file structures?

And how can we make our resources more reusable for each operation, especially in something like ( index & show ),

We can differentiate between inside responses using this route name,

So If we don't want to show all attributes in the index, we can hide them from the index resource.

Here's our example:

  • We defined our route in the api.php code:
Route::apiResource('/posts', ApiPostController::class, ['only' => ['index', 'show']]);
Enter fullscreen mode Exit fullscreen mode
  • Now in our resource, We put a condition when the request coming from a route named posts.show:
        $routeShowPost = $request->routeIs('posts.show');
Enter fullscreen mode Exit fullscreen mode

And here's our PostResource, with the power of mergeWhen(), we can show or hide the attributes from the resource:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Route;

class PostResource extends JsonResource
{
    public function toArray($request)
    {
        $routeShowPost = $request->routeIs('posts.show');

        return [
            'id' => $this->id,
            'title' => $this->title,
            'image' => $this->image,
            'created_at' => $this->created_at,
            $this->mergeWhen($routeShowPost, [
                'content' => $this->content,
                'comments' => CommentResource::collection($this->whenLoaded('comments'))
            ]),
            'user' => UserResource::make($this->whenLoaded('user')),
            'category' => GeneralResource::make($this->whenLoaded('category')),
            'tags' => GeneralResource::collection($this->whenLoaded('tags')),
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

In our example, we show the post's content and comments only when the route is posts.show.

Thanks for reading,

Top comments (0)