mastermindlegion's avatar

Paginate Collection

Hello guys, please help me with paginating collection please.

I'm using approach to add this in appServiceProvider (https://gist.github.com/simonhamp/549e8821946e2c40a617c85d2cf5af5e)

Collection::macro('paginate', function($perPage, $total = null, $page = null, $pageName = 'page') { $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

        return new LengthAwarePaginator(
            $this->forPage($page, $perPage),
            $total ?: $this->count(),
            $perPage,
            $page,
            [
                'path' => LengthAwarePaginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ]
        );
    });
}

this: I have this in my controller -> $collection = new ArticlesCollection( ArticleResource::collection(Article::with(['user', 'tags'])->paginate(2))); return $collection; It succesfully returns the two items per page -> ?page=... is working

But I have no meta tags included -> how many pages I have and so on... Please with including it. Thank you and with the best regards Martin

0 likes
17 replies
MichalOravec's avatar
Level 75

@mastermindlegion Create this service provider and add it to your config/app.php under providers key.

<?php

namespace App\Providers;

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Support\ServiceProvider;

class ExtendCollectionServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap services.
     *
     * @return void
     */
    public function boot()
    {
        Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
            $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

            return new LengthAwarePaginator($this->forPage($page, $perPage), $total ?: $this->count(), $perPage, $page, [
                'path' => LengthAwarePaginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ]);
        });
    }

    /**
     * Register services.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}
1 like
mastermindlegion's avatar

Hello, thank you for replie.

So as you said I have created and registered ExtendCollectionServiceProvider, but there is the same result, where I got fetched collection, but with no meta...

mastermindlegion's avatar

the first paginated page return an array of objects -> [ objects- 4 paginated ] and after the ?page=2 + it returns an array [ extraObj.{ {paginated objects} } ]

Do you have clue how to get rid of the extra object? here:

Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
        $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

        return new LengthAwarePaginator($this->forPage($page, $perPage), $total ?: $this->count(), $perPage, $page, [
            'path' => 'articles',
            'pageName' => $pageName,
        ]);
    });
MichalOravec's avatar

This pagination on collection should work at same way like normal pagination in Query Builder, I don't have any problems with that.

1 like
mastermindlegion's avatar

Thanks for replie, this should be more explained

1.) The first return ?page=1 ->>>>>

response.data [
  {
    id: 1,
    user: {
      id: 1,
      full_name: 'test [email protected]',
      email: '[email protected]'
    },
    slug: 'davonte-sawayn-1',
    name: '1',
    body: 'Aliquam placeat veritatis alias sed et inventore. Animi animi amet recusandae qui voluptates quidem. Eos qui culpa aut molestias.',
    tags: [ [Object], [Object], [Object] ],
    time: {
      created_at: '2020-05-05T15:19:26.000000Z',
      updated_at: '2020-05-05T15:19:26.000000Z'
    }
  },
    ...... REST OF THE OBJECTS ....
]

2.) return after ?page=2 ++ ->>>>>>

response.data {
  '5': {
    id: 11,
    user: {
      id: 1,
      full_name: 'test [email protected]',
      email: '[email protected]'
    },
    slug: 'raphaelle-hudson-jr-1',
    name: '3',
    body: 'Maiores in ullam error odio accusantium rerum aliquam. Numquam explicabo fugiat facilis natus accusantium. Non et perferendis fugit in quas ipsum voluptate sit.',
    tags: [],
    time: {
      created_at: '2020-05-06T12:18:51.000000Z',
      updated_at: '2020-05-06T12:18:51.000000Z'
    }
  }

  ...... the rest
}
mastermindlegion's avatar

Code in ExtendCollectionServiceProvider:

  Collection::macro('paginate', function ($perPage, $total = null, $page = null, $pageName = 'page') {
            $page = $page ?: LengthAwarePaginator::resolveCurrentPage($pageName);

            return new LengthAwarePaginator($this->forPage($page, $perPage), $total ?: $this->count(), $perPage, 				$page, [
                'path' => 'articles',
                'pageName' => $pageName,
            ]);
        });

This is same as you said, didn't change anything

My controller:

 $collection = new ArticlesCollection(
      ArticleResource::collection(Article::with(['user', 'tags'])->get())->paginate(4));
     return $collection;

The first pagination ?page=1 returns:

response.data [
  {
    id: 1,
    user: {
      id: 1,
      full_name: 'test [email protected]',
      email: '[email protected]'
    },
    slug: 'davonte-sawayn-1',
    name: '1',
    body: 'Aliquam placeat veritatis alias sed et inventore. Animi animi amet recusandae qui voluptates quidem. Eos qui culpa aut molestias.',
    tags: [ [Object], [Object], [Object] ],
    time: {
      created_at: '2020-05-05T15:19:26.000000Z',
      updated_at: '2020-05-05T15:19:26.000000Z'
    }
  },
    ...... REST OF THE OBJECTS ....
]

I got array of objects as expected -> this is what I want, that s awesome,but

The returns after ?page= 2 and more always returns an object instead of arrays :( :

 {
  '5': {
    id: 11,
    user: {
      id: 1,
      full_name: 'test [email protected]',
      email: '[email protected]'
    },
    slug: 'raphaelle-hudson-jr-1',
    name: '3',
    body: 'Maiores in ullam error odio accusantium rerum aliquam. Numquam explicabo fugiat facilis natus accusantium. Non et perferendis fugit in quas ipsum voluptate sit.',
    tags: [],
    time: {
      created_at: '2020-05-06T12:18:51.000000Z',
      updated_at: '2020-05-06T12:18:51.000000Z'
    }
  }

  ...... the rest
}
MichalOravec's avatar

It will be something wrong with ArticlesCollection and ArticleResource::collection

Because when use it like it works, of course this is just example, in this case you can just just normal paginate instead of get.

$items = Item::where('active', true)->get()->paginate(20);
mastermindlegion's avatar

I will dig deep into it. Thanks anyways for replies and help :). have a great day

mastermindlegion's avatar

@michaloravec Hello Michal, sorry for disturbing, but would you know how to add meta tags in this pagination?

Thank you very much. I'm certain it would help many people

This is my controller:

 $collection = new ArticlesCollection(
      ArticleResource::collection(Article::with(['user', 'tags'])->paginate(3)));
     return $collection;
    }

This is my response:

{
"data": [
{
"id": 1,
"user": {
"id": 1,
"full_name": "test [email protected]",
"email": "[email protected]"
},
"slug": "davonte-sawayn-1",
"name": "1",
"body": "Aliquam placeat veritatis alias sed et inventore. Animi animi amet recusandae qui voluptates quidem. Eos qui culpa aut molestias.",
"tags": [
{
"id": 6,
"name": "testTag"
},
{
"id": 1,
"name": "PHP"
},
{
"id": 2,
"name": "Laravel"
}
],
"time": {
"created_at": "2020-05-05T15:19:26.000000Z",
"updated_at": "2020-05-05T15:19:26.000000Z"
}
},
{
"id": 2,
"user": {
"id": 1,
"full_name": "test [email protected]",
"email": "[email protected]"
},
"slug": "lura-weimann-iii-1",
"name": "2",
"body": "Praesentium velit deserunt eaque quia consequatur dolor. Delectus nulla quasi in maiores. Et recusandae sed et magnam aperiam exercitationem dolor et.",
"tags": [
{
"id": 3,
"name": "Node"
},
{
"id": 2,
"name": "Laravel"
}
],
"time": {
"created_at": "2020-05-05T15:19:26.000000Z",
"updated_at": "2020-05-05T15:19:26.000000Z"
}
},
{
"id": 11,
"user": {
"id": 1,
"full_name": "test [email protected]",
"email": "[email protected]"
},
"slug": "raphaelle-hudson-jr-1",
"name": "3",
"body": "Maiores in ullam error odio accusantium rerum aliquam. Numquam explicabo fugiat facilis natus accusantium. Non et perferendis fugit in quas ipsum voluptate sit.",
"tags": [],
"time": {
"created_at": "2020-05-06T12:18:51.000000Z",
"updated_at": "2020-05-06T12:18:51.000000Z"
}
}
]
}
mastermindlegion's avatar

@michaloravec hey there, problem was that I wasn't using static collection. This example works well:

        return  ArticleResource::collection(Article::with(['user', 'tags'])->paginate(3));

1 like

Please or to participate in this conversation.