ahoi's avatar
Level 5

"Nested pagination": Paginate (sub-)item in ApiResource

Hello everybody,

I got an ApiResource like this:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Gate;


class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id'     => $this->id,
            'name'   => $this->name,
            'email'  => $this->email,
            'status' => $this->status,
        ];
    }
    
}

Now I'd like to add a relation to this: Items:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\JsonResource;
use Illuminate\Support\Facades\Gate;


class UserResource extends JsonResource
{
    /**
     * Transform the resource into an array.
     *
     * @param  \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function toArray($request)
    {
        return [
            'id'     => $this->id,
            'name'   => $this->name,
            'email'  => $this->email,
            'items'  => new ItemResourceCollection
            ($this->items()->paginate(5)),
            'status' => $this->status,
        ];
    }
    
}

This is ItemResourceCollection:

<?php

namespace App\Http\Resources;

use Illuminate\Http\Resources\Json\ResourceCollection;


class ItemResourceCollection extends ResourceCollection
{
    /**
     * Transform the resource collection into an array.
     *
     * @param  \Illuminate\Http\Request $request
     *
     * @return array
     */
    public function toArray($request)
    {
        return [
            'current_page'   => $this->resource->currentPage(),
            'first_page_url' => $this->resource->url(1),
            'from'           => $this->resource->firstItem(),
            'last_page'      => $this->resource->lastPage(),
            'last_page_url'  => $this->resource->url($this->lastPage()),
            'next_page_url'  => $this->resource->nextPageUrl(),
            'per_page'       => $this->resource->perPage(),
            'prev_page_url'  => $this->resource->previousPageUrl(),
            'to'             => $this->resource->lastItem(),
            'total'          => $this->resource->total(),
            'data'           => $this->collection->transform(function ($item) {
                return [
                    'id'          => $item->id,
                    'title'       => $item->title,
                    'status'      => $item->status,
                ];
            }),
        ];
    }
}

Well - this is the result:

{
  "data": {
    "id": 1,
    "name": "John Doe",
    "email": "[email protected]",
    "items": {
      "current_page": 1,
      "first_page_url": "http://example.org/api/user/1?page=1",
      "from": 1,
      "last_page": 1,
      "last_page_url": "http://example.org/api/user/1?page=1",
      "next_page_url": null,
      "per_page": 5,
      "prev_page_url": null,
      "to": 1,
      "total": 1,
      "data": [
        {
          "id": 1,
          "title": "Test",
          "description": "<p>Test</p>",
          "status": "published"
        }
      ]
    },
    "status": "active"
  }
}

Hm, it seems that this does not really work, because the page-urls are referring the parent model and not the relation?

I would love to see something like: http://example.org/api/user/items?page=1 or something like that and fetch the results using Axios on my frontend:

axios.get ('/api/user/items?page=' + this.pagination.current_page + '&length=' + this.pagination.per_page);

Any idea whether this is possible?

Otherwise I would have to create a route for /user/items/index or something like that and return data from there.

0 likes
3 replies
jlrdw's avatar
jlrdw
Best Answer
Level 75

Have two divs, one paginate next parent, other paginate children.

https://i.imgur.com/6nGcvF7.jpg

Was just done as a quick demo a while back, thus no formatting.

Such as this is used for accounts receivable, i.e., next company, and can paginate through the companies receivables.

Note, laravel does not solve everything, you may have to code your own custom paginator.

Asking for code on how is redundant, as writing a paginator is so easy, not to mention there are thousands of examples of writing a custom paginator already. Just some simple math involved.

My quick example only had next, but previous would be easy to add in.

1 like
ahoi's avatar
Level 5

Thanks for your reply :-)

Actually I was asking for a "Laravel-like" solution for that to prevent custom coding. As I don't see a better solution, I guess I have to write my own pagination method for that :-)

Please or to participate in this conversation.