4

I need to load model relations in it's resource and paginate them.

In my case i have Category and Path models, plus CategoryResource and PathResource

The toArray method of CategoryResource is like below:

public function toArray($request)
{
    return [
        'id'   => $this->id,
        'name' => $this->name,
        'slug' => $this->slug,
        'order' => $this->order,
        'paths' => PathResource::collection($this->whenLoaded('paths'))
    ];
}

and toArray method of PathResource is like below:

public function toArray($request)
{
    return parent::toArray($request);
}

Question is how can i load and paginate related Path's in my CategoryResource?

Rahmat Waisi
  • 1,293
  • 1
  • 15
  • 36
Kareimovich
  • 591
  • 1
  • 7
  • 18

2 Answers2

1

I had same problem and solved it this way:

Prerequisites

You must have/create a resource for Path model i.e. PathResource to create one use this command:

php artisan make:resource PathResource

Solution

The solution is to use laravel paginate on relation and use transform method on the paginated collection to convert it's items to your resource.

First Step

Create a base class for paginating any resource in your app, using this command:

php artisan make:resource PaginatedCollection -c

Edit the PaginatedCollection and add following codes:

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;

class PaginatedCollection extends ResourceCollection
{

    /**
     * An array to store pagination data that comes from paginate() method.
     * @var array
     */
    protected $pagination;

    /**
     * PaginatedCollection constructor.
     *
     * @param mixed $resource paginated resource using paginate method on models or relations.
     */
    public function __construct($resource)
    {

        $this->pagination = [
            'total' => $resource->total(), // all models count
            'count' => $resource->count(), // paginated result count
            'per_page' => $resource->perPage(),
            'current_page' => $resource->currentPage(),
            'total_pages' => $resource->lastPage()
        ];

        $resource = $resource->getCollection();

        parent::__construct($resource);
    }

    /**
     * Transform the resource collection into an array.
     * now we have data and pagination info.
     *
     * @param \Illuminate\Http\Request $request
     * @return array
     */
    public function toArray($request)
    {
        return [
            // our resources
            'data' => $this->collection,

            // pagination data
            'pagination' => $this->pagination
        ];
    }
}

Second Step

make a collection resource for your model and extend PaginatedCollection instead of default ResourceCollection.

Run this command to do so:
php artisan make:resource PathCollection -c

Now edit your new collection class PathCollection and override toArray method:

/**
 * Transform the resource collection into an array.
 *
 * In this method use your already created resources
 * to avoid code duplications
 *
 * @param \Illuminate\Http\Request $request
 * @return array
 */
public function toArray($request)
{
    return [

        // Here we transform any item in paginated items to a resource

        'data' => $this->collection->transform(function ($path) {
            return new PathResource($path);
        }),

        'pagination' => $this->pagination,
    ];
}

Final Step

In your CategoryResource use PathCollection like this:

return [
    'id'   => $this->id,
    'name' => $this->name,
    'slug' => $this->slug,
    'order' => $this->order,
    'paths' => new PathCollection(
        new LengthAwarePaginator(
            $this->whenLoaded('paths'),
            $this->paths_count,
            10
        )
    ),
];

and make sure you import LengthAwarePaginator class:
use Illuminate\Pagination\LengthAwarePaginator;

Usage

$category = Category::with('paths')->withCount('paths')->find(1);
return new CategoryResource($category);
Rahmat Waisi
  • 1,293
  • 1
  • 15
  • 36
-1

You should probably checkout the documentation on Resources and ResourceCollections. ResourceCollections will allow you to easily paginate your resources. Api Resource Collection Pagination Documentation

Logan Craft
  • 589
  • 4
  • 9
  • The documentation only shows how you can paginate a whole model. The question is how can you paginate a relation of the model inside the resource in the toArray method? – Billion Shiferaw Aug 03 '20 at 14:43