How can I paginate an array of objects in Laravel?
Asked Answered
M

7

8

I'm building an application using Laravel 4.2. I have a model for units and another for users and pivot table user_units. Every user in this application can select a unit and add it to his favorite list then he can publish this unit with his information as an ad.

I want to select all units published by all users

The user_units (pivot) table has the following columns:

id   
user_id 
unit_id 
publish      
adtype       
addinfo          
created_at  
updated_at

With relations methods on models

public function users() {
    return $this->belongsToMany('User', 'user_units')
                ->withPivot('id','publish', 'adtype', 'addinfo');
}

public function units() {
    return $this->belongsToMany('Unit', 'user_units')
                ->withPivot('id','publish', 'adtype', 'addinfo');
}

My query to select all published units by all users

// Get all published units by users for sale. 
    $users = User::all();
    $publishedSaleUnits = [];
    foreach($users as $user){
        $userUnits = $user->units()->orderBy('adtype', 'desc')->get();
        if(count($userUnits)){
            foreach($userUnits as $unit){
                if($unit->pivot->publish == 1 && $unit->unit_purpose_id == 1){
                    if( $unit->pivot->adtype ){
                        //push all featured ads onto the beginning of array
                        array_unshift($publishedSaleUnits, $unit);
                    }else{
                        //push all normal ads onto the end of array
                        array_push($publishedSaleUnits, $unit);
                    }
                }
            }
        }
    }

Now I got the result but I can't use pagination with results because it's an array of objects.

So is there any better solution to get all published units by user with pagination?

Mcwherter answered 21/11, 2014 at 15:37 Comment(0)
C
35

according to this article https://www.itsolutionstuff.com/post/how-to-create-pagination-from-array-in-laravelexample.html

you can paginate your array by creating a custom method and using LengthAwarePaginator

namespace App\Http\Controllers;
  
use Illuminate\Http\Request;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;
use Illuminate\Pagination\LengthAwarePaginator;
  
class PaginationController extends Controller
{
    public function index()
    {
        $myArray = [
            ['id'=>1, 'title'=>'Laravel CRUD'],
            ['id'=>2, 'title'=>'Laravel Ajax CRUD'],
            ['id'=>3, 'title'=>'Laravel CORS Middleware'],
        ];
  
        $data = $this->paginate($myArray);
        return view('paginate', compact('data'));
    }
   
    public function paginate($items, $perPage = 5, $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);
    }
}
Comedic answered 13/8, 2020 at 10:1 Comment(3)
perfect answer.Rube
Same example Not working in API for laravel 8Hardiness
Tested and tweaked a bit to use on my code using laravel 8.Kamasutra
S
6

Your approach to query the data is extremely inefficient. Fetch your data in one query. Nested traversing is not only hard to read but also a performance killer.

To the pagination problem:

Laravel provides a Pagignator Factory. With it you will be able to build your own Paginator with your own data.

It's as easy as

$units = Paginator::make($unit, count($unit), 10);

if you're using the Facade. Otherwise Illuminate\Pagination\Factory is the class you are looking for.

Senzer answered 21/11, 2014 at 15:51 Comment(2)
$units = Paginator::make($units, count($units), 10); i try this method before it create $units->links() in view perfect but every page contains all results from $units arrayMcwherter
i have used paginator::make to paginate the records in the $publishedSaleUnits array. But in view i am getting the pagination links, but all links has all records in it. how to restrict it to perPage items.Mcwherter
S
4

You can try my code with your own array,

$page = isset($request->page) ? $request->page : 1; // Get the page=1 from the url
$perPage = $pagination_num; // Number of items per page
$offset = ($page * $perPage) - $perPage;

$entries =  new LengthAwarePaginator(
    array_slice($contact_list, $offset, $perPage, true),
    count($contact_list), // Total items
    $perPage, // Items per page
    $page, // Current page
    ['path' => $request->url(), 'query' => $request->query()] // We 
       need this so we can keep all old query parameters from the url
);
Shurlock answered 8/2, 2018 at 5:15 Comment(0)
C
2

Using Laravel 8, if any of you are having trouble in the paginator getting lost with the URL after page 1, just add in the LengthAwarePaginator options parameter the URL path for you original page.

Example:

return new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page, ['path' => 'users']);
Cumquat answered 19/4, 2023 at 2:13 Comment(0)
M
1

I got a better solution to paginate array result and I found the answer here

Paginator::make function we need to pass only the required values instead of all values. Because paginator::make function simply displays the data send to it. To send the correct offset paginated data to the paginator::make, the following method should be followed

    $perPage = 5;   
    $page = Input::get('page', 1);
    if ($page > count($publishedSaleUnits) or $page < 1) { $page = 1; }
    $offset = ($page * $perPage) - $perPage;
    $perPageUnits = array_slice($publishedSaleUnits,$offset,$perPage);
    $pagination = Paginator::make($perPageUnits, count($publishedSaleUnits), $perPage);
Mcwherter answered 21/11, 2014 at 17:45 Comment(0)
D
0

this code work for me on laravel 8

use Illuminate\Pagination\Paginator;
use Illuminate\Support\Collection;


    public function paginate($items, $perPage = 5, $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);
    }

according to this refrence https://www.itsolutionstuff.com/post/how-to-create-pagination-from-array-in-laravelexample.html

Dilatant answered 10/9, 2022 at 12:37 Comment(0)
S
0

This worked for me:

<?php

namespace App\Utils;

use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator;
use \Illuminate\Support\Facades\Request;

class Paginate
{
    public static function paginate($items, $perPage = 10, $page = null)
    {
        $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
        $total = count($items);
        $currentpage = $page;
        $offset = ($currentpage * $perPage) - $perPage ;
        $itemstoshow = array_slice($items , $offset , $perPage);


        return new LengthAwarePaginator($itemstoshow, $total, $perPage, $page,
            ['path'=> Request::fullUrl()]);
    }
}

You can visit this link as well: Laravel Create Pagination From Array Tutorial

Syringa answered 13/6, 2023 at 15:11 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.