Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to remove query string page from the first page of laravel pagination?

I'm using laravel-5.4 pagination like the following:

public function index()
    {
        $jobs = Job::paginate(5);
        return view('job.index', compact('jobs'));
    }

In the view:

{{ $jobs->links() }}

There is a problem of generating two typical pages: /job and /job?page=1 the two page has the same contents.

I want to do anything that removes the query string page from the first page of the pagination.

I have tried the following:

if ($jobs->onFirstPage()){
  $jobs->setPageName('');
} 

But this corrupt the pagination, i.e the links of pages does not load correctly and the query string value remains for all pages.

like image 754
SaidbakR Avatar asked Mar 14 '17 01:03

SaidbakR


3 Answers

The effective solution for this issue that I have found is to edit the pagination template.

First publish the pagination template from the vendors using the following command from the root of the project:

php artisan vendor:publish --tag=laravel-pagination

Now a file at resources/views/vendor/pagination/default.blade.php should be found and it could be edited like the following using str_replace() for the urls of each page and back navigation button:

<li><a href="{{str_replace('?page=1','',$paginator->previousPageUrl())}}" title="{{__('Previous')}}" rel="prev">{{$foxPrev}}</a></li>

and

 <li><a href="{{str_replace('?page=1','',$url)}}">{{ $page }}</a></li>

Update:

A bug was found with ?page=10 so instead of using str_replace we should using preg_replace like the following:

<li><a href="{{preg_replace('/\?page=[1]$/','',$url)}}">{{ $page }}</a></li>

Update 2:

In case of using any customized name for the page number parameter other than page, we could use the paginator getter for the $pageName property like the following in the pagination template:

<li><a href="{{preg_replace('/\?'.$paginator->getPageName().'=[1]$/','',$url)}}">{{ $page }}</a></li>

To know more about how to use more than one pagination on the same page or how to customize the page number parameter $pageName from view, checkout this answer

like image 163
SaidbakR Avatar answered Oct 26 '22 22:10

SaidbakR


You can extend LengthAwarePaginator method url($page)

/**
 * Get the URL for a given page number.
 *
 * @param  int  $page
 * @return string
 */
public function url($page)
{
    if ($page <= 0) {
        $page = 1;
    }

    // If we have any extra query string key / value pairs that need to be added
    // onto the URL, we will put them in query string form and then attach it
    // to the URL. This allows for extra information like sortings storage.
    $parameters = ($page > 1) ? [$this->pageName => $page] : [];

    if (count($this->query) > 0) {
        $parameters = array_merge($this->query, $parameters);
    }

    return rtrim($this->path
        .(Str::contains($this->path, '?') ? '&' : '?')
        .http_build_query($parameters, '', '&')
        .$this->buildFragment(), '?');
}
like image 40
Aksi Avatar answered Oct 26 '22 23:10

Aksi


improved Aksi answer

app/Services/CustomLengthAwarePaginator.php

<?php

namespace App\Services;

use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Arr;
use Illuminate\Support\Str;

class CustomLengthAwarePaginator extends LengthAwarePaginator
{
    /**
     * Get the URL for a given page number.
     *
     * @param  int  $page
     * @return string
     */
    public function url($page)
    {
        if ($page <= 0) {
            $page = 1;
        }

        // If we have any extra query string key / value pairs that need to be added
        // onto the URL, we will put them in query string form and then attach it
        // to the URL. This allows for extra information like sortings storage.
        $parameters = ($page > 1) ? [$this->pageName => $page] : [];

        if (count($this->query) > 0) {
            $parameters = array_merge($this->query, $parameters);
        }

        return $this->path()
            . (count($parameters) > 0
                ? (Str::contains($this->path(), '?') ? '&' : '?')
                : '')
            . Arr::query($parameters)
            . $this->buildFragment();
    }
}

in AppServiceProvider.php or another

public function boot()
{
    app()->bind(LengthAwarePaginator::class, CustomLengthAwarePaginator::class);
}
like image 30
Dmitry Turov Avatar answered Oct 26 '22 22:10

Dmitry Turov