Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

axtg's avatar
Level 5

API collections and resource

I'd like to build an API that adheres to the JSONAPI standard. So I'm using Collections and Resource classes to return a structured response.

When I return a collection I'm told here to have two parent items, links and data. So I'm making my ResourceCollection look like this:

/api/v1/posts

return [
            'links' => [
                'self' => url()->current(),
            ],
            'data' => $this->collection,
        ];

Returns:

{
	"links": {
		"self": "http:\/\/localhost\/api\/v1\/installations"
	},
	"data": [
		{
			"type": "installations",
			"id": 1,
			...

Good.

By using $this->collection I'm automatically calling my Resource class. This is a nice feature, but the format differs from when I would call that resource directly (e.g. /api/v1/posts/1).

The code of Resource class

 return [
            'links' => [
                'self' => url()->current(),
            ],
            'data' => [
                'type' => 'installations',
                'id' => $this->id,
                'attributes' =>
                [
                    'title' => $this->title,
                ],
                'relationships' =>
                [
					//
				]
		]
];

Calling that directly works nicely, BUT now my Collection class is "messed up" (below). I don't want the links showing for the Resource class when called via the Collection class and no repetition of the data element. The parent data should just include objects.

{
	"links": {
		"self": "http:\/\/localhost\/api\/v1\/installations"
	},
	"data": [
		{
			"links": {
				"self": "http:\/\/localhost\/api\/v1\/installations"
			},
			"data": {
				"type": "installations",
				"id": 1,
				"attributes": {
					"title": "MOOS Office"
				},
			}
		}
	]
}

Is there any way I can alter the Resource class depending on how it's called? Anyone got best practice experience here?

0 likes
4 replies
martinbean's avatar
Level 80

@axtg You don’t need to return links and data explicitly. Eloquent resources will automatically contain data. So use the same resource class for both a single resource and a collection of resources:

return new FooResource($foo);
return FooResource::collection($foos);

For a collection, Laravel will automatically include links with pagination data.

drewdan's avatar

If you didn't want to build all of this yourself, Spatie have a package for Laravel which does a lot of this out of the box for you, it's a wrapper around the phpleague fractal package:

https://github.com/spatie/laravel-fractal

We use this to make our JSON API, and it creates the relevant data links, relationships etc and handles a lot of the heavy lifting for you. The package includes a JSON API serializer, which you can read a little more about here:

https://fractal.thephpleague.com/serializers/

axtg's avatar
Level 5

Thanks @drewdan , I'll give that a look. I also looked at Laravel Orion. There seem some initiatives out there. But to bet on long term support is always tricky.

@martinbean Its actually surprising I didn't realize the difference between ModelCollection and ModelResource::collection. That's probably going to help me on my way this time around.

drewdan's avatar

@axtg Oh yes, nothing worse than banking on a package to find the maintainer has gone AWOL or decide to abandon a package, but in that case you can always fork and carry on the work. Spatie are very good though. From what I have seen, they only tend to abandon stuff which has a better solution to replace it, or if the ability gets added to the core of Laravel, for example.

Please or to participate in this conversation.