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

russellxu's avatar

Why do we need Collection classes since the returing structure of paginated json is all the same?

I build an api server by laravel 12. I used Resource class all the time and it's very handy and necessary. But I don't get why we need Collection classes,since the returing structure of paginated json is all the same? So here is my resouce class and collection class looks like:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Request;
use Illuminate\Http\Resources\Json\ResourceCollection;

class JobListCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @return array<int|string, mixed>
     */
    public function toArray(Request $request): array
    {
        return collection_response_body()->call($this);
    }
}

if (!function_exists('collection_response_body')) {
    function collection_response_body(): Closure
    {
        return fn() => [
            'data' => $this->collection,
            'meta' => [
                'current_page' => $this->resource->currentPage(),
                'from' => $this->resource->firstItem(),
                'last_page' => $this->resource->lastPage(),
                'path' => $this->resource->path(),
                'per_page' => $this->resource->perPage(),
                'to' => $this->resource->lastItem(),
                'total' => $this->resource->total(),
            ],
            'links' => [
                'first' => $this->resource->url(1),
                'last' => $this->resource->url($this->resource->lastPage()),
                'prev' => $this->resource->previousPageUrl(),
                'next' => $this->resource->nextPageUrl(),
            ],
        ];
    }
}

And I use Collection class like this in Controller:

    public function list(): JsonResponse
    {
        $jobs = Job::query()
            ->available()
            ->paginate();

        return $this->successResponse(
            JobListCollection::make($jobs)
        );

As I said , since the structure of paginated json I need return is all the same, and meanwhile I need take use of Collection class to wrap Paginated results. To pervent duplicated code all over my Collection class, the only thing I can came out is to make a collection_response_body function.

My question is why do we need Collection class, I got all kinds of Collection classes and all looks the same, Can I get rid of them and only keep Resources class in my project?

0 likes
3 replies
LaryAI's avatar
Level 58

Great question! This is a common point of confusion when working with Laravel API Resources and Collections.

Why do Collection classes exist?

Resource classes (JsonResource) are meant to transform a single model instance.
Collection classes (ResourceCollection) are meant to transform a collection of models (e.g., paginated results), and to optionally customize the outer structure of the response (like adding meta, links, etc.).

What happens if you only use Resource classes?

If you return a paginated result like this:

return JobListResource::collection($jobs);

Laravel will automatically wrap the collection in a ResourceCollection behind the scenes. By default, it will return a structure like:

{
    "data": [
        // resource array here
    ],
    "links": { ... },
    "meta": { ... }
}

So, for most use-cases, you do NOT need to create a custom Collection class unless you want to customize the outer structure, add extra meta, or change the way the collection is serialized.

Why might you want a custom Collection class?

  • Custom meta or links: If you want to add extra fields to the response (e.g., custom meta, statistics, etc.), you need a custom Collection class.
  • Consistent structure: If you want to enforce a specific response structure for all collections, you can do it in your Collection class.
  • Reusability: If you want to encapsulate logic for a specific resource collection, a Collection class is the right place.

Your case

You noticed that all your Collection classes look the same, and you're using a helper to avoid code duplication. That's a good approach!
If you don't need to customize the collection response for different resources, you can avoid creating custom Collection classes and just use the default behavior.

You can simply do:

return JobListResource::collection($jobs);

Laravel will handle the pagination structure for you.

TL;DR

  • You don't need custom Collection classes unless you want to customize the response.
  • Resource classes are enough for most APIs.
  • Laravel's default collection handling is usually sufficient.

Example:

public function list(): JsonResponse
{
    $jobs = Job::query()
        ->available()
        ->paginate();

    return response()->json(
        JobListResource::collection($jobs)
    );
}

This will return the standard paginated structure.


Summary Table:

Use Case What to Use
Transform a single model Resource class
Transform a collection (default structure) Resource::collection()
Customize collection response Custom Collection class

Conclusion:
If all your collection responses are the same, you can skip custom Collection classes and just use Resource::collection($collection). Only create a Collection class if you need to customize the response structure.

Let me know if you need an example of customizing a Collection class!

russellxu's avatar

@LaryAI To do as Lary said, use JobListResource instead of JobListCollection ,is will only return an array of dataset, no meta info, no links info. It's not I wanted

        return $this->successResponse(
            //JobListCollection::make($jobs)
            JobListResource::collection($jobs)
        );

Please or to participate in this conversation.