loading...

★ A package that adds resource links to your Laravel API resources

freekmurze profile image Freek Van der Herten Originally published at freek.dev on ・3 min read

At Spatie we have several projects where the UI is rendered using JavaScript (we're big fans of Inertia). The backend and routes are defined in the Laravel app. The backend sends information to the frontend using API resources.

We often add the available routes the frontend can use as links property on the resource. To avoid having to add all routes manually, my colleague Ruben released a package, called laravel-resource-links that can automatically add resource links to the API resource.

In this post, I'd like to introduce the package to you.

A first example

Imagine you have a UsersController with index, show, create, edit, store, update and delete methods. You want to add these routes to a UserResource.

This is how you do that using our package. You apply the Spatie\ResourceLinks\HasLinks trait use the links method.

class UserResource extends JsonResource
{
    use Spatie\ResourceLinks\HasLinks;
    use Spatie\ResourceLinks\HasMeta;

    public function toArray($request): array
    {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'links' => $this->links(UsersController::class),
        ];
    }
}

When rendering that resource to json this will be the result:

{
   "data":[
      {
         "id":1,
         "name": "Ruben Van Assche",
         "links": {
            "show": "https://laravel.app/users/1",
            "edit": "https://laravel.app/users/1/edit",
            "update": "https://laravel.app/users/1",
            "delete": "https://laravel.app/users/1"
         }
      }
   ],
}

That works fine for routes that revolve around an instance of your resource (in this example: a single user). But what about routes by a single instance, such as index and create?

You can take care of those routes by applying the HasMeta trait and adding a meta function to your resource.

class UserResource extends JsonResource
{
    use Spatie\ResourceLinks\HasMeta;

    // ...

    public static function meta()
    {
        return [
            'links' => self::collectionLinks(UsersController::class),
        ];
    }
}

This is how that resource will be rendered:

{
   "data":[
      {
         "id":1,
         "name": "Ruben Van Assche",
         "links": {
            "show": "https://laravel.app/users/1",
            "edit": "https://laravel.app/users/1/edit",
            "update": "https://laravel.app/users/1",
            "delete": "https://laravel.app/users/1"
         }
      }
   ],
   "meta": {
      "links": {
         "index": "https://laravel.app/users",
         "create": "https://laravel.app/users/create",
         "store": "https://laravel.app/users"
      }
   }
}

Customizing the json structure

You can change the structure of how things are rendered to json. In the config file of the package, you can specify the serializer class to be used. A serializer is responsible for building the output of the links of a resource.

The package ships with a few different serializers. In the example in the previous section, the LinkSerializer is used (that's the one that is used by default).

If you use ExtendedLinkSerializer the links will include the HTTP verb of a link.

"links": {
    "index": {
        'method': 'get',
        'action': "https://laravel.app/users"
    },
    "update": {
        'method': 'put',
        'action': "https://laravel.app/users/1"     
    },
}

You can also write your own serializer to customize the behavior to your heart's content.

Closing thoughts

This package came in handy in several projects. It provides quite some more options. Read the documention to know more.

Thanks Ruben for the excellent work!

Be sure to also check out the other packages our team has created previously.

Discussion

pic
Editor guide