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);