Skip to content

Instantly share code, notes, and snippets.

@vluzrmos
Created July 20, 2016 14:31
Show Gist options
  • Save vluzrmos/3ce756322702331fdf2bf414fea27bcb to your computer and use it in GitHub Desktop.
Save vluzrmos/3ce756322702331fdf2bf414fea27bcb to your computer and use it in GitHub Desktop.
Laravel Paginate Collection or Array
<?php
/**
* Gera a paginação dos itens de um array ou collection.
*
* @param array|Collection $items
* @param int $perPage
* @param int $page
* @param array $options
*
* @return LengthAwarePaginator
*/
public function paginate($items, $perPage = 15, $page = null, $options = [])
{
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
$items = $items instanceof Collection ? $items : Collection::make($items);
return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, $options);
}
@Kaylakaze
Copy link

Kaylakaze commented Nov 5, 2020

Better yet, just make a macro.

Collection::macro('paginate', function($perPage = 15, $page = null, $options = []) {
            $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
            if (!isset($options['path'])) {
                $options['path'] = '/' . request()->path();
            }
            return new LengthAwarePaginator(array_values($this->forPage($page, $perPage)->toArray()), $this->count(), $perPage, $page, $options);
        });

@kanchanarandika
Copy link

Thank you very much! This is really helpful

@MarouanAfkir
Copy link

For those who has issues with second page:

where 2nd page data has keys like:

"data": {
    "5": {
    "userId": "564110eadcb39832268ea873",
    "email": "[email protected]",
    "isActive": true,
    "firstName": "dsdfgdfg",
    "lastName": "dsdfgdfg",
    "permissionType": "dsdfgdfg"
    },
    "6": {
    "userId": "564110ea2169bc358a3b65c2",
    "email": "[email protected]",
    "isActive": false,
    "firstName": "dsdfgdfg",
    "lastName": "dsdfgdfg",
    "permissionType": "dsdfgdfg"
    },
    "7": {
    "userId": "564110eaee662f30c4bd6772",
    "email": "[email protected]",
    "isActive": true,
    "firstName": "dsdfgdfg",
    "lastName": "dsdfgdfg",
    "permissionType": "dsdfgdfg"
    },
}

This is because forPage() returns an array with keys

Fix is to add array_values():

  public function paginateCollection($items, $perPage = 15, $page = null, $options = [])
    {
        $page = $page ?: (\Illuminate\Pagination\Paginator::resolveCurrentPage() ?: 1);
        $items = $items instanceof \Illuminate\Support\Collection ? $items : \Illuminate\Support\Collection::make($items);
        return new \Illuminate\Pagination\LengthAwarePaginator(array_values($items->forPage($page, $perPage)->toArray()), $items->count(), $perPage, $page, $options);
        //ref for array_values() fix: https://stackoverflow.com/a/38712699/3553367
    }

Thanks, mate

@Tuhedul-Islam
Copy link

/**

  • Gera a paginação dos itens de um array ou collection.
  • @param array|Collection $items
  • @param int $perPage
  • @param int $page
  • @param array $options
  • @return LengthAwarePaginator
    */
    public function paginate($items, $perPage = 2, $page = null)
    {
    $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
    $items = $items instanceof Collection ? $items : Collection::make($items);
    return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, [
    'path' => Paginator::resolveCurrentPath(),
    'pageName' => 'page',
    ]);
    }

Thanks a lot

@mosesegboh
Copy link

please how can it be installed??

@Kaylakaze
Copy link

Depends on which one you're talking about. For the macro, you put it in your boot() method on AppServiceProvider (or on another service provider if you want). For the general method, you specify a custom collection object for your model and put it on the custom collection.

@cnyambo
Copy link

cnyambo commented Mar 8, 2021

With the same code, I have two pages, one for search where I enter the search criteria and another to display the results. However, when I click to the second or any other page, the system redirect me first to the search page again to reenter the search criteria then bring the result for that specific page. Could you please help to solve this?

@Sarmed-armis
Copy link

great for this comments thanks to all

@Gab-Arruda
Copy link

Great!! It works just fine. Thanks a lot!!!

@mdbtekny
Copy link

Hello to everyone, how can i use ->links()? Thanks in advance

@vladimir-zarcanin
Copy link

If you have a problem with pagination add values() method:
return new LengthAwarePaginator($items->forPage($page, $perPage)->values(), $count, $perPage, $page, []);

@Tuhedul-Islam
Copy link

Tuhedul-Islam commented Feb 17, 2022 via email

@vladimir-zarcanin
Copy link

I have a problems when fetch page > 1, $items->forPage($page, $perPage)->values(). this solved my problems.

@NaungYeHtet
Copy link

This type of pagination can impact performance?

@Kings-Israel
Copy link

Thanks very much

@waiylkarim
Copy link

waiylkarim commented Mar 7, 2023

Laravel 9.x and above

	public static function paginate(array|Collection $items, mixed $perPage = null, mixed $page = null, array $options = [], mixed $path = null)
	{
		$perPage = is_null($perPage) ? 25 : $perPage;
		
		$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
	
		$items = $items instanceof Collection ? $items : Collection::make($items);
	
		$paginator = new LengthAwarePaginator(
			$items->forPage($page, $perPage), 
			$items->count(), 
			$perPage, 
			$page, 
			$options
		);

		if(!is_null($path)) {
			$paginator->setPath($path);
		}

		return $paginator;
	}

Basic Example:

        // set path dynamically from current route name or url with params
        $path = route(request()->route()->getName(), $request->except(['page']));
        
        $invoices = YOUR_HELPER_CLASS_HERE::paginate(
            items: $data, 
            perPage: 10, 
            path: $path
        );

@masroore
Copy link

masroore commented Aug 27, 2023

Laravel 10.x / PHP 8.2 and above:

public static function paginate(
	array|Collection $items,
	?int $perPage = null,
	?int $page = null,
	array $options = [],
	?string $path = null
): LengthAwarePaginator {
	$perPage ??= 50;
	$page ??= Paginator::resolveCurrentPage(default: 1);
	$path ??= Paginator::resolveCurrentPath();

	$items = $items instanceof Collection ? $items : Collection::make($items);

	$paginator = new LengthAwarePaginator(
		$items->forPage($page, $perPage),
		$items->count(),
		$perPage,
		$page,
		$options
	);

	if (!blank($path)) {
		$paginator = $paginator->setPath($path);
	}

	return $paginator;
}

Usage:

$paginated_list = Helper_Class::paginate($list_of_items);

@ofumbi
Copy link

ofumbi commented Feb 10, 2024

Collection::macro('paginate', function($perPage = 15, $page = null, $options = []) {
$page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
if (!isset($options['path'])) {
$options['path'] = '/' . request()->path();
}
return new LengthAwarePaginator(array_values($this->forPage($page, $perPage)->toArray()), $this->count(), $perPage, $page, $options);
});

Failed in L10
Place this in the boot method of your App\Providers\AppServiceProvider;

 Collection::macro('paginate', function ($perPage = 15, $page = null, $options = []) {
    $page = $page ?: (\Illuminate\Pagination\Paginator::resolveCurrentPage() ?: 1);
    return new \Illuminate\Pagination\LengthAwarePaginator(array_values($this->forPage($page, $perPage)->toArray()), $this->count(), $perPage, $page, $options);
});

Use like this

$perPage = 5;
collect([1,2,3,4,5])->paginate($perPage)

@mickela
Copy link

mickela commented Feb 26, 2024

Great, thanks! 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment