Laravel collection and cache data to paginate

Published on Sep 20, 2022

Pagination is important to fetch data. It loads fast & gives a small amount of data which helps to load a huge amount of data. Here I have an example of 60K posts data where I just fetch the id & title. As usual, I just create a post table where I have stored necessary data. So I'm not showing the migration table. Here I also show you the cache data where I store 60K post data.

routes/web.php
Route::get('cache-posts', [PostController::class, 'cachePost'])->name('cache_post');
Route::get('items', [PostController::class, 'item'])->name('item');
Route::get('clear', [PostController::class, 'clear'])->name('cache_clear');

At first, I show the router file where I have 3 route one show the cache data another one clears the cache data, and 3rd one show the data from the array object. Here I convert array to object you can do the same thing with an array but you need to modify the blade file if you want this with array data.

app/Http/Controllers/PostController.php
<?php

namespace App\Http\Controllers;


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

class PostController extends Controller
{
    public function cachePost()
    {
        $checked = Cache::has('posts');

        if($checked) {
            $posts = Cache::get('posts');
            $posts = $this->paginate($posts, 'cache-posts');
        } else {
            $posts = Post::select('id', 'title')->orderBy('id', 'ASC')->get();
            Cache::put('posts', $posts);
            $posts = $this->paginate($posts, 'cache-posts');
        }

        return view('posts.index', compact('posts'));
    }

    public function paginate($items, $pageName = null, $perPage = 15, $page = null, $options = [])
    {
        $page = $page ?: (Paginator::resolveCurrentPage() ?: 1);
        $items = $items instanceof Collection ? $items : Collection::make($items);
        $data = new LengthAwarePaginator($items->forPage($page, $perPage), $items->count(), $perPage, $page,$options);
        if($pageName) {
            $data->setPath($pageName);
        }
        return $data;
    } 

}

Actually, at the first moment when i load the page it fetch the all post id & title and put them in the cache file. So it make as a collection. So next time when reloading this page it loaded data from the cache file. No Model call at that moment. Most of the time when we paginate something we just fetch data and at the end, we called `->paginate()` this function but this one does not work in the collection. We create a custom paginate function where we return the LengthAwarePaginator. We just send the collection in this custom $this->paginate() function. The most important thing is we must assign the $pageName variable for proper work of pagination. Otherwise it not work properly cause if we don't pass that the link will be like this. example.com/?page=1 if we pass the page name the link will be example.com/pageName?page=1.

app/Http/Controllers/PostController.php
<?php

namespace App\Http\Controllers;


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

class PostController extends Controller
{
         public function item() 
    {
        $item1 = [
            (object) ['id' => 1, 'title' => 'hello teddy'],
            (object) ['id' => 2, 'title' => 'hello buuny'],
            (object) ['id' => 3, 'title' => 'hello jonny'],
            (object) ['id' => 4, 'title' => 'hello ronny'],
            (object) ['id' => 5, 'title' => 'hello monny'],
        ];

        $item2 =  [
            (object) ['id' => 6, 'title' => 'hello orrpra'],
            (object) ['id' => 7, 'title' => 'hello teddaa'],
            (object) ['id' => 8, 'title' => 'hello polly'],
            (object) ['id' => 9, 'title' => 'hello salsa'],
            (object) ['id' => 10, 'title' => 'hello laila'],
        ];

        $items = collect($item1)->merge($item2);
        $posts = $this->paginate($items, 'items', 2);

        return view('posts.index', compact('posts'));

    }

    public function clear()
    {
        Cache::flush();
    }
}

Not only collection we also work on array data. here you see I used (object) before the array but you can use only array if you want. if you used array you must change in view file like -> to []. Okay, let's check the blade file 👇

resources/views/file_location.php
@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row justify-content-center">
        <div class="col-md-8">
            <h3>Posts</h3>
            <table class="table">
                <thead>
                    <tr>
                        <th scope="col">id</th>
                        <th scope="col">title</th>
                    </tr>
                </thead>
                <tbody>
                    @foreach ($posts as $post)
                    <tr>
                        <th scope="row">{{ $post->id }}</th>
                        <td>{{ $post->title }}</td>
                    </tr>
                    @endforeach
                </tbody>
            </table>
            <br>
            @if($posts->hasPages())
            {{ $posts->links() }}
            @endif
        </div>
    </div>
</div>

@endsection

So, this is the way of paginate of a collection.

I hope this article help you a little bit. If you like this type of content please bookmark this.I am also a big fan of Tailwindcss, so you check out our website for Tailwindcss template and components 👇
tailkitpro.com

Comments (0)