Custom pagination view in Laravel 5

2020-01-24 10:58发布

Laravel 4.2 has the option to specify a custom view in app/config/view.php such as:

/*
|--------------------------------------------------------------------------
| Pagination View
|--------------------------------------------------------------------------
|
| This view will be used to render the pagination link output, and can
| be easily customized here to show any view you like. A clean view
| compatible with Twitter's Bootstrap is given to you by default.
|
*/
'pagination' => 'pagination_slider-alt'

This is gone in Laravel 5 at least regarding view.php.

Is there a way to replicate this behavior in Laravel 5?

19条回答
聊天终结者
2楼-- · 2020-01-24 11:14

In 5.5 links() is replaced with render() which appears to work similarly. [Official DOC]

replace

{{ $replies->links() }}

with

{{ $replies->render("pagination::default") }}

Following commands will generate Pagination template in resources/views/vendor/pagination

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

In any view file (blade files) you can use those template like following ex:

  • {{ $replies->render("pagination::default") }}
  • {{ $replies->render("pagination::bootstrap-4") }}
  • {{ $replies->render("pagination::simple-bootstrap-4") }}
  • {{ $replies->render("pagination::semantic-ui") }}
查看更多
够拽才男人
3楼-- · 2020-01-24 11:18

Laravel 5 ships with a Bootstrap 4 paginator if anyone needs it.

First create a new service provider.

php artisan make:provider PaginationServiceProvider

In the register method pass a closure to Laravel's paginator class that creates and returns the new presenter.

<?php


namespace App\Providers;

use Illuminate\Pagination\BootstrapFourPresenter;
use Illuminate\Pagination\Paginator;
use Illuminate\Support\ServiceProvider;

class PaginationServiceProvider extends ServiceProvider
{
    /**
     * Bootstrap the application services.
     *
     * @return void
     */
    public function boot()
    {
        //
    }

    /**
     * Register the application services.
     *
     * @return void
     */
    public function register()
    {
        Paginator::presenter(function($paginator)
        {
            return new BootstrapFourPresenter($paginator);
        });
    }
}

Register the new provider in config/app.php

'providers' => [
    //....
    App\Providers\PaginationServiceProvider::class,
]

I found this example at Bootstrap 4 Pagination With Laravel

查看更多
老娘就宠你
4楼-- · 2020-01-24 11:20

A quick JS fix for Bootstrap 4 pagination in Laravel 5+

Simply place the below script within your page:

    <script>
            $('.pagination li').addClass('page-item');
            $('.pagination li a').addClass('page-link');
            $('.pagination span').addClass('page-link');

    </script>

Advantages: saves server CPU, needs no adjustments in your app.

查看更多
疯言疯语
5楼-- · 2020-01-24 11:20

I am using Laravel 5.8. Task was to make pagination like next http://some-url/page-N instead of http://some-url?page=N. It cannot be accomplished by editing /resources/views/vendor/pagination/blade-name-here.blade.php template (it could be generated by php artisan vendor:publish --tag=laravel-pagination command). Here I had to extend core classes.

My model used paginate method of DB instance, like next:

        $essays = DB::table($this->table)
        ->select('essays.*', 'categories.name', 'categories.id as category_id')
        ->join('categories', 'categories.id', '=', 'essays.category_id')
        ->where('category_id', $categoryId)
        ->where('is_published', $isPublished)
        ->orderBy('h1')
        ->paginate( // here I need to extend this method
            $perPage,
            '*',
            'page',
            $page
        );

Let's get started. paginate() method placed inside of \Illuminate\Database\Query\Builder and returns Illuminate\Pagination\LengthAwarePaginator object. LengthAwarePaginator extends Illuminate\Pagination\AbstractPaginator, which has public function url($page) method, which need to be extended:

    /**
 * 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 = [$this->pageName => $page];

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

    // this part should be overwrited
    return $this->path 
        . (Str::contains($this->path, '?') ? '&' : '?')
        . Arr::query($parameters)
        . $this->buildFragment();
}

Step by step guide (part of information I took from this nice article):

  1. Create Extended folder in app directory.
  2. In Extended folder create 3 files CustomConnection.php, CustomLengthAwarePaginator.php, CustomQueryBuilder.php:

2.1 CustomConnection.php file:

namespace App\Extended;

use \Illuminate\Database\MySqlConnection;

/**
 * Class CustomConnection
 * @package App\Extended
 */
class CustomConnection extends MySqlConnection {
    /**
     * Get a new query builder instance.
     *
     * @return \App\Extended\CustomQueryBuilder
     */
    public function query() {
        // Here core QueryBuilder is overwrited by CustomQueryBuilder
        return new CustomQueryBuilder(
            $this,
            $this->getQueryGrammar(),
            $this->getPostProcessor()
        );
    }
}

2.2 CustomLengthAwarePaginator.php file - this file contains main part of information which need to be overwrited:

namespace App\Extended;

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

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

        // here the MAIN overwrited part of code BEGIN
        $parameters = [];

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

        $path =  $this->path . "/{$this->pageName}-$page";
        // here the MAIN overwrited part of code END

        if($parameters) {
            $path .= (Str::contains($this->path, '?') ? '&' : '?') . Arr::query($parameters);
        }

        $path .= $this->buildFragment();

        return $path;
    }
}

2.3 CustomQueryBuilder.php file:

namespace App\Extended;

use Illuminate\Container\Container;
use \Illuminate\Database\Query\Builder;

/**
 * Class CustomQueryBuilder
 * @package App\Extended
 */
class CustomQueryBuilder extends Builder
{
    /**
     * Create a new length-aware paginator instance.
     * Overwrite paginator's class, which will be used for pagination
     *
     * @param  \Illuminate\Support\Collection  $items
     * @param  int  $total
     * @param  int  $perPage
     * @param  int  $currentPage
     * @param  array  $options
     * @return \Illuminate\Pagination\LengthAwarePaginator
     */
    protected function paginator($items, $total, $perPage, $currentPage, $options)
    {
        // here changed
        // CustomLengthAwarePaginator instead of LengthAwarePaginator
        return Container::getInstance()->makeWith(CustomLengthAwarePaginator::class, compact(
            'items', 'total', 'perPage', 'currentPage', 'options'
        ));
    }
}
  1. In /config/app.php need to change db provider:

    'providers' => [
    
    
    // comment this line        
    // illuminate\Database\DatabaseServiceProvider::class,
    
    // and add instead:
    App\Providers\CustomDatabaseServiceProvider::class,
    
  2. In your controller (or other place where you receive paginated data from db) you need to change pagination's settings:

    // here are paginated results
    $essaysPaginated = $essaysModel->getEssaysByCategoryIdPaginated($id, config('custom.essaysPerPage'), $page);
    // init your current page url (without pagination part)
    // like http://your-site-url/your-current-page-url
    $customUrl = "/my-current-url-here";
    // set url part to paginated results before showing to avoid 
    // pagination like http://your-site-url/your-current-page-url/page-2/page-3 in pagination buttons
    $essaysPaginated->withPath($customUrl);
    
  3. Add pagination links in your view (/resources/views/your-controller/your-blade-file.blade.php), like next:

    <nav>
        {!!$essays->onEachSide(5)->links('vendor.pagination.bootstrap-4')!!}
    </nav>
    

ENJOY! :) Your custom pagination should work now

查看更多
爷、活的狠高调
6楼-- · 2020-01-24 11:20

If you want to change the page number in url instead of get data like /pageNo. ex: /2. you can use jquery to change url . I have some data in get method with the url.

$(function () {
  $('.pagination li a').each(function () {
    var link = $(this).attr('href');
    var pageText = $(this).text();
    var activePage = parseInt($('.pagination li.active span').text());
    if (pageText.trim() == "«") {
      pageText = activePage - 1;
    } else if (pageText.trim() == "»") {
      pageText = activePage + 1;
    }
    link = link.replace('?', '/' + pageText + '?');
    link = link.replace('&page=' + pageText, '');
    $(this).attr('href', link);
    console.log(link);
  });
})
查看更多
贼婆χ
7楼-- · 2020-01-24 11:21

if you want to beautify the appearance of your pagination, I use the class from bootstrap to make it more simple and easy

 @if ($students->lastPage() > 1)
        <ul class="pagination ml-auto">
            <li class="{{ ($students->currentPage() == 1) ? ' disabled' : '' }} page-item">
                <a class=" page-link " href="{{ $students->url(1) }}" aria-label="Previous">
                    <span aria-hidden="true">&laquo;</span>
                    <span class="sr-only">Previous</span>
                </a>
            </li>
            @for ($i = 1; $i <= $students->lastPage(); $i++)
                <li class="{{ ($students->currentPage() == $i) ? ' active' : '' }} page-item">
                    <a class=" page-link " href="{{ $students->url($i) }}">{{ $i }}</a>
                </li>
            @endfor
            <li class="{{ ($students->currentPage() == $students->lastPage()) ? ' disabled' : '' }} page-item">
                <a href="{{ $students->url($students->currentPage()+1) }}" class="page-link" aria-label="Next">
                    <span aria-hidden="true">&raquo;</span>
                    <span class="sr-only">Next</span>
                </a>
            </li>
        </ul>
@endif
查看更多
登录 后发表回答