DEV Community

Grant
Grant

Posted on

Laravel Inertia and API Resources

If you haven't checked out Inertia, it's worth a look. It's sort of like a hybrid SPA. I've built a few apps with it and don't see myself not using it for the next while.

Let's take a look at a nice server side tip that I find really useful.

Say we're working on our /users/{user} route. Assume we have a show method in our UserController:

public function show(User $user)
{
    // This is just a helper for Inertia\Inertia::render()
    return inertia('User', [
        'user' => $user,
    ]);
}
Enter fullscreen mode Exit fullscreen mode

This will be totally valid and fine. When your user variable gets sent to the front end, it will be converted to an array with the $user->toArray() method. You can define that on App\User and all will be good.

But what happens when you have relationships that you'd like included or you'd like your app to be more flexible? Then you would reach for API Resources. Resources allow you to define the shape of your objects when they get sent to API's. Since Inertia is sort of like using an API, we can leverage API Resources to make our objects be sent to our views more reliably and consistently.

php artisan make:resource UserResource
Enter fullscreen mode Exit fullscreen mode

This generates app/Http/Resources/UserResource.php.

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;

class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'email' => $this->email,
        ];
    }
}
Enter fullscreen mode Exit fullscreen mode

We can refactor our controller to return our resource instead:

public function show(User $user)
{
    return inertia('User', [
        'user' => new \App\Http\Resources\UserResource($user),
    ]);
}
Enter fullscreen mode Exit fullscreen mode

Behind the scenes, Inertia will convert this to its "response" version as if you were returning it directly from your controller, but allows you to return a resource for each variable you want to return to your views.

We can go one step further to make things "cleaner" and easier to use when you have multiple controllers returning the same resource. I'm lazy so I like this.

In our App\User model, let's add a method called toResource and return that resource.

public function toResource()
{
    return new \App\Http\Resources\UserResource($this);
}
Enter fullscreen mode Exit fullscreen mode

The final state of our controller looks like this:

public function show(User $user)
{
    return inertia('User', [
        'user' => $user->toResource(),
    ]);
}
Enter fullscreen mode Exit fullscreen mode

I love API Resources. Coupled with Inertia, it's a really great developer experience on top of an already amazing experience with Laravel. Make sure to check out Inertia and API Resources. The real power with API Resources comes with relationships!

Top comments (7)

Collapse
 
silverdes profile image
OUAIJI ABDELAZIZ

Hello!
That's exactly what I was looking for.
Thank you so much.

Collapse
 
carbontwelve profile image
Simon Dann

A benefit of this approach is that you can check to see if the request requires json and return the resource directly, that way you can have the same controller method handle api and web requests without duplication.

This is what I have done with one application that has a mobile app needing to communicate on some endpoints.

Collapse
 
bhaviljain68 profile image
bhaviljain68

Hey, neat idea.
How exactly would you do this?
Can you provide an example please?

Collapse
 
najibu profile image
Najibu Nsubuga

You could use UserResource::make($user) instead of creating a new method toResource.

Collapse
 
luisfws profile image
Luís Fernando

Muito bom!

Collapse
 
timoogo profile image
timogo • Edited

Then how are we supposed to use this resource ?
Great article overall

Collapse
 
benz738 profile image
Federico R.