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.
Top comments (0)