简体   繁体   English

限制 Laravel 分页显示的链接数量

[英]Limit amount of links shown with Laravel pagination

Any easy way to limit how many links are shown with Laravels pagination?有什么简单的方法可以限制 Laravels 分页显示的链接数量吗?

Currently it shows 13 links at most (Prev, 1 2 3 4 5 7 8.. 78 79 next)目前最多显示13个链接(Prev, 1 2 3 4 5 7 8.. 78 79 next)

This however is too much for mobile devices and becomes a two line navigation... is there any way to set the links to eg only show 10?然而,这对于移动设备来说太多了,变成了两行导航...有没有办法将链接设置为例如只显示 10?

I have messed around with the pagination presenter but nothing actually seemed to work.我弄乱了分页演示器,但实际上似乎没有任何效果。

Thanks谢谢

I used css to limit the links that I allowed.我使用 css 来限制我允许的链接。 Really simple.. this can be extended to show any number of pages, at any number of breakpoints真的很简单……这可以扩展到在任意数量的断点处显示任意数量的页面

@media screen and ( max-width: 400px ){

    li.page-item {

        display: none;
    }

    .page-item:first-child,
    .page-item:nth-child( 2 ),
    .page-item:nth-last-child( 2 ),
    .page-item:last-child,
    .page-item.active,
    .page-item.disabled {

        display: block;
    }
}

this specific implementation allows the arrows, the '...', the first page, active page and last page这个特定的实现允许箭头,'...',第一页,活动页和最后一页

Now Laravel 5.7 has a new pagination method to customize the number of links on each side of the paginator.现在 Laravel 5.7 有一个新的分页方法来自定义分页器每一侧的链接数量。 Thanks to the new method you no longer need a custom pagination view in some cases.由于采用了新方法,在某些情况下您不再需要自定义分页视图。 Here's the API you can use to define the link count on each side of the current page:以下是可用于定义当前页面每一侧的链接计数的 API:

User::paginate(10)->onEachSide(2);

write that code on your controller.在您的控制器上编写该代码。

you can see more detail at https://laravel-news.com/laravel-5-7-pagination-link-customizations您可以在https://laravel-news.com/laravel-5-7-pagination-link-customizations查看更多详细信息

For Laravel 5.6+对于 Laravel 5.6+

Publish vendor template:发布供应商模板:

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

Edit bootstrap-4.blade.php as following:编辑bootstrap-4.blade.php如下:

@if ($paginator->hasPages())
<ul class="pagination" role="navigation">
    {{-- Previous Page Link --}}
    @if ($paginator->onFirstPage())
        <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.previous')">
            <span class="page-link" aria-hidden="true">&lsaquo;</span>
        </li>
    @else
        <li class="page-item">
            <a class="page-link" href="{{ $paginator->previousPageUrl() }}" rel="prev" aria-label="@lang('pagination.previous')">&lsaquo;</a>
        </li>
    @endif

    <?php
        $start = $paginator->currentPage() - 2; // show 3 pagination links before current
        $end = $paginator->currentPage() + 2; // show 3 pagination links after current
        if($start < 1) {
            $start = 1; // reset start to 1
            $end += 1;
        } 
        if($end >= $paginator->lastPage() ) $end = $paginator->lastPage(); // reset end to last page
    ?>

    @if($start > 1)
        <li class="page-item">
            <a class="page-link" href="{{ $paginator->url(1) }}">{{1}}</a>
        </li>
        @if($paginator->currentPage() != 4)
            {{-- "Three Dots" Separator --}}
            <li class="page-item disabled" aria-disabled="true"><span class="page-link">...</span></li>
        @endif
    @endif
        @for ($i = $start; $i <= $end; $i++)
            <li class="page-item {{ ($paginator->currentPage() == $i) ? ' active' : '' }}">
                <a class="page-link" href="{{ $paginator->url($i) }}">{{$i}}</a>
            </li>
        @endfor
    @if($end < $paginator->lastPage())
        @if($paginator->currentPage() + 3 != $paginator->lastPage())
            {{-- "Three Dots" Separator --}}
            <li class="page-item disabled" aria-disabled="true"><span class="page-link">...</span></li>
        @endif
        <li class="page-item">
            <a class="page-link" href="{{ $paginator->url($paginator->lastPage()) }}">{{$paginator->lastPage()}}</a>
        </li>
    @endif

    {{-- Next Page Link --}}
    @if ($paginator->hasMorePages())
        <li class="page-item">
            <a class="page-link" href="{{ $paginator->nextPageUrl() }}" rel="next" aria-label="@lang('pagination.next')">&rsaquo;</a>
        </li>
    @else
        <li class="page-item disabled" aria-disabled="true" aria-label="@lang('pagination.next')">
            <span class="page-link" aria-hidden="true">&rsaquo;</span>
        </li>
    @endif
</ul>
@endif

This example handle in a correct way new CSS classes, active link, three dots (correctly, not 1..2 3 4) and is it customizable (number of pages that you want to show).此示例以正确的方式处理新的 CSS 类、活动链接、三个点(正确地,不是 1..2 3 4)并且是否可自定义(您要显示的页面数)。

Example例子

Three dots handled correctly正确处理三个点

From laravel 8 docs . 来自 laravel 8 文档 If needed, you may control how many additional links are displayed on each side of the current page using the onEachSide method in blade:如果需要,您可以使用刀片中的onEachSide方法控制当前页面每一侧显示的附加链接数量:

{{ $posts->onEachSide(1)->links() }}

I had created a new custom presenter to show only 10 links.我创建了一个新的自定义演示者来仅显示 10 个链接。 It involves 3 steps:它包括3个步骤:

Create your own custom presenter创建您自己的自定义演示者

use Illuminate\Pagination\BootstrapPresenter;

class CustomPresenter extends BootstrapPresenter{
    protected function getPageSlider()
    {
        // Changing the original value from 6 to 3 to reduce the link count
        $window = 3;

        // If the current page is very close to the beginning of the page range, we will
        // just render the beginning of the page range, followed by the last 2 of the
        // links in this list, since we will not have room to create a full slider.
        if ($this->currentPage <= $window)
        {
            $ending = $this->getFinish();

            return $this->getPageRange(1, $window + 2).$ending;
        }

        // If the current page is close to the ending of the page range we will just get
        // this first couple pages, followed by a larger window of these ending pages
        // since we're too close to the end of the list to create a full on slider.
        elseif ($this->currentPage >= $this->lastPage - $window)
        {
            $start = $this->lastPage - 8;

            $content = $this->getPageRange($start, $this->lastPage);

            return $this->getStart().$content;
        }

        // If we have enough room on both sides of the current page to build a slider we
        // will surround it with both the beginning and ending caps, with this window
        // of pages in the middle providing a Google style sliding paginator setup.
        else
        {
            $content = $this->getAdjacentRange();

            return $this->getStart().$content.$this->getFinish();
        }
    }

} 

Create your own pagination view (eg custom-paginator.php), place in your views folder创建您自己的分页视图(例如 custom-paginator.php),放置在您的视图文件夹中

<ul class="pagination">
    <?php echo with(new CustomPresenter($paginator))->render(); ?>
</ul>

Update your app/config.view.php更新您的应用程序/config.view.php

'pagination' => 'custom-paginator',

By making the following changes, you will able to get a 10 links paginator.通过进行以下更改,您将能够获得一个 10 个链接的分页器。

Hope this help :D希望这有帮助:D

Create one file default.blade.php in new pagination folder in view folder with below code.使用以下代码在视图文件夹中的新分页文件夹中创建一个文件 default.blade.php。 That means you have override core pagination file with our new pagination file.这意味着您已经使用我们的新分页文件覆盖了核心分页文件。 That will set some limit in pagination link.这将在分页链接中设置一些限制。

@if ($paginator->hasPages())
    <ul class="pagination pagination">
        {{-- Previous Page Link --}}
        @if ($paginator->onFirstPage())
            <li class="disabled"><span>«</span></li>
        @else
            <li><a href="{{ $paginator->previousPageUrl() }}" rel="prev">«</a></li>
        @endif

        @if($paginator->currentPage() > 3)
            <li class="hidden-xs"><a href="{{ $paginator->url(1) }}">1</a></li>
        @endif
        @if($paginator->currentPage() > 4)
            <li><span>...</span></li>
        @endif
        @foreach(range(1, $paginator->lastPage()) as $i)
            @if($i >= $paginator->currentPage() - 2 && $i <= $paginator->currentPage() + 2)
                @if ($i == $paginator->currentPage())
                    <li class="active"><span>{{ $i }}</span></li>
                @else
                    <li><a href="{{ $paginator->url($i) }}">{{ $i }}</a></li>
                @endif
            @endif
        @endforeach
        @if($paginator->currentPage() < $paginator->lastPage() - 3)
            <li><span>...</span></li>
        @endif
        @if($paginator->currentPage() < $paginator->lastPage() - 2)
            <li class="hidden-xs"><a href="{{ $paginator->url($paginator->lastPage()) }}">{{ $paginator->lastPage() }}</a></li>
        @endif

        {{-- Next Page Link --}}
        @if ($paginator->hasMorePages())
            <li><a href="{{ $paginator->nextPageUrl() }}" rel="next">»</a></li>
        @else
            <li class="disabled"><span>»</span></li>
        @endif
    </ul>
@endif

Then Where you want to get pagination then you have to call laravel pagination function with this view file parameter.然后你想在哪里分页然后你必须用这个视图文件参数调用laravel分页函数。

 $data->links('pagination.default')

I know it's an old question but there is still no way to set in using function links() parameters.我知道这是一个老问题,但仍然无法使用函数 links() 参数进行设置。 I made simple jQuery code, maybe it will help someone.我做了简单的 jQuery 代码,也许它会对某人有所帮助。 It's much simplier than Zesky's answer.这比Zesky的回答简单得多。 I don't mean better, just simplier :)我的意思不是更好,只是更简单:)

JavaScript: JavaScript:

(function($) {
    $('ul.pagination li.active')
        .prev().addClass('show-mobile')
        .prev().addClass('show-mobile');
    $('ul.pagination li.active')
        .next().addClass('show-mobile')
        .next().addClass('show-mobile');
    $('ul.pagination')
        .find('li:first-child, li:last-child, li.active')
        .addClass('show-mobile');
})(jQuery);

CSS: CSS:

@media (max-width: /* write what you need, for me it's 560px */) {
    ul.pagination li:not(.show-mobile) {
        display: none;
    }
}

This code make visible only few li elements.此代码仅使少数 li 元素可见。 Active, two before, two after, prev/next arrows.活动,两个之前,两个之后,上一个/下一个箭头。 That make only 7 visible elements at most instead of 15.这最多只能生成 7 个可见元素,而不是 15 个。

The old way of defining a custom presenter doesn't work with Laravel 5.3+, the number of links shown seems to be hard-coded in the $onEachSide parameter of Illuminate/Pagination/UrlWindow::make() :定义自定义演示者的旧方法不适用于 Laravel 5.3+,显示的链接数量似乎是硬编码在Illuminate/Pagination/UrlWindow::make()$onEachSide参数中:

public static function make(PaginatorContract $paginator, $onEachSide = 3)

I ended up just writing my own render() function, stealing some code from LengthAwarePaginator我最终只是编写了自己的 render() 函数,从LengthAwarePaginator窃取了一些代码

/**
     * Stole come code from LengthAwarePaginator::render() and ::elements() to allow for a smaller UrlWindow
     *
     * @param LengthAwarePaginator $paginator
     * @param int $onEachSide
     * @return string
     */
    public static function render(LengthAwarePaginator $paginator, $onEachSide = 2)
    {
        $window = UrlWindow::make($paginator, $onEachSide);

        $elements = array_filter([
            $window['first'],
            is_array($window['slider']) ? '...' : null,
            $window['slider'],
            is_array($window['last']) ? '...' : null,
            $window['last'],
        ]);

        return LengthAwarePaginator::viewFactory()->make(LengthAwarePaginator::$defaultView, [
            'paginator' => $paginator,
            'elements' => $elements,
        ])->render();
    }
}

We use Twig, so I registered this as a Twig filter, I imagine something similar could be done for Blade.我们使用 Twig,所以我将它注册为 Twig 过滤器,我想可以为 Blade 做类似的事情。

My table was too narrow so, I decided to show only first and the last li (The Next and Back arrows) of pagination with jQuery filter().我的表太窄了,所以我决定用 jQuery filter() 只显示分页的第一个和最后一个 li(下一个和后退箭头)。 You can customize this further.您可以进一步自定义。

$('ul.pagination li').hide().filter(':lt(1), :nth-last-child(1)').show();

Make sure to add it before the end of body tag.确保在 body 标签结束之前添加它。

It's an old question, but just thought I'd share how I've recently achieved reducing the number of pagination links in a Laravel 5.2 application:这是一个老问题,但我只是想分享一下我最近如何减少Laravel 5.2应用程序中的分页链接数量:

Inside your ViewServiceProvider :在您的ViewServiceProvider

 \Illuminate\Pagination\AbstractPaginator::presenter(function($paginator) {
      return new \App\Pagination\BootstrapPresenter($paginator);
 });

App\\Pagination\\BootstrapPresenter.php应用\\分页\\BootstrapPresenter.php

<?php namespace App\Pagination;

use Illuminate\Pagination\UrlWindow;
use Illuminate\Contracts\Pagination\Paginator as PaginatorContract;
use Illuminate\Pagination\BootstrapThreePresenter as LaravelBootstrapThreePresenter;

class BootstrapPresenter extends LaravelBootstrapThreePresenter
{
    /**
     * Create a new Bootstrap presenter instance.
     *
     * @param  \Illuminate\Contracts\Pagination\Paginator  $paginator
     * @param  \Illuminate\Pagination\UrlWindow|null  $window
     * @return void
     */
    public function __construct(PaginatorContract $paginator, UrlWindow $window = null)
    {
        $this->paginator = $paginator;

        // Make the pagination window smaller (default is 3).
        $this->window = UrlWindow::make($paginator, 1);
    }
}

From:从:

在此处输入图片说明

To:到:

在此处输入图片说明

I solved this issue after trying everything.我尝试了一切后解决了这个问题。 This code is specifically for those who are facing this issue on SPA;此代码专门针对那些在 SPA 上遇到此问题的人; in my case, I am using Vue but it's simple function to sort the array of links:就我而言,我使用的是 Vue,但它是对链接数组进行排序的简单函数:

<li  v-for="link in sliceLinks(links)"

sliceLinks(array){
            let index , start, end = 0;
            let newArray = [];
            index = array.findIndex(o => o.active === true );
            start = index < 5 ? index-1 : index == array.length-2 ? index-4 : index == array.length-3 ? index-3 : index > 5 ? index - 2 : index -2;
            end = index == 1 ? index + 5 : index > 5 ? index + 3 : index == 5 ? index + 3 : index + 4;
            newArray = array.slice(start,end);
            return newArray;
        },

Just pass your array of links to this function and it will show 2 before and 2 after the active link.只需将您的链接数组传递给此函数,它就会在活动链接之前显示 2 个,在活动链接之后显示 2 个。 The output will look look like this:输出将如下所示:

在此处输入图像描述

There are many ways to go about it depending on exactly how you want it to behave.有很多方法可以解决它,具体取决于您希望它的行为方式。

For my needs, I wanted a quick solution to shorten it up so it doesn't break my mobile layouts.根据我的需要,我想要一个快速的解决方案来缩短它,这样它就不会破坏我的移动布局。

Laravel 5.3 Laravel 5.3

Edit this file: (or the one you're using in your paginator calls)编辑此文件:(或您在分页器调用中使用的文件)

/vendor/pagination/bootstrap-4.blade.php

I add a single line to break out of the link rendering loop after 2 links.在 2 个链接之后,我添加了一行以跳出链接呈现循环。

{{-- Array Of Links --}}
    @if (is_array($element))
        @foreach ($element as $page => $url)
             @if ($page == $paginator->currentPage())
                 <li class="page-item active"><span class="page-link">{{ $page }}</span></li>
              @else
                  <li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
                  {{--Add the line below to limit rendered links--}}
                  <?php if($loop->count > 2) break; ?>
              @endif
         @endforeach
     @endif

This is an older question, but none of the answers here are up to date with the latest Laravel documentation.这是一个较旧的问题,但这里的答案都不是最新的 Laravel 文档。 For newer versions of Laravel (Laravel 5.6+), there is a somewhat easy fix to this problem, but it does take publishing the vendor pagination views, as per Laravel Documentation .对于较新版本的 Laravel(Laravel 5.6+),这个问题有一个比较简单的解决方法,但是根据Laravel 文档,它确实需要发布供应商分页视图。 Assuming you haven't already published or changed the default pagination view, the command you run is:假设您尚未发布或更改默认分页视图,您运行的命令是:

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

Once the views are published, you will find bootstrap-4.blade.php in the resources/views/vendor/pagination directory.视图发布后,您将在 resources/views/vendor/pagination 目录中找到 bootstrap-4.blade.php。 You can edit this file and make the pagination links appear however you want.您可以编辑此文件并根据需要显示分页链接。 In order to reduce the number of links displayed by default, I simply used a little bit of inline php to set an index and limit the number of links to display, as shown below:为了减少默认显示的链接数量,我简单地使用了一点inline php设置了一个索引,限制了显示的链接数量,如下图:

{{-- Array Of Links --}}
@if (is_array($element))
    <?php $index = 0; ?>
    @foreach ($element as $page => $url)
        @if($index<4)
            @if ($page == $paginator->currentPage())
                <li class="page-item active" aria-current="page"><span class="page-link">{{ $page }}</span></li>
            @else
                <li class="page-item"><a class="page-link" href="{{ $url }}">{{ $page }}</a></li>
            @endif
        @endif
        <?php $index++ ?>
    @endforeach
@endif

Most of this code is in the default blade view for bootstrap-4.blade.php, but I added the $index=0, $index<4, $index++ code to LIMIT the number of links on the left side of the paginator to 4.大部分代码都在 bootstrap-4.blade.php 的默认刀片视图中,但我添加了 $index=0, $index<4, $index++ 代码来限制分页器左侧的链接数量4.

This is the correct way to handle this problem as per Laravel documentation, without editing composer vendor files, or trying to hack the system in some other way.这是根据 Laravel 文档处理此问题的正确方法,无需编辑 Composer 供应商文件,或尝试以其他方式破解系统。 I do realize that JR Lawhorne posted a similar answer, but it does not include the entire process of publishing the vendor file before posting.我确实意识到 JR Lawhorne 发布了类似的答案,但它不包括发布前发布供应商文件的整个过程。 Hope this helps others.希望这对其他人有帮助。

If you only want to show only one page, then here is a way of doing it in Laravel 8.x:如果你只想显示一个页面,那么在 Laravel 8.x 中有一种方法可以做到这一点:

@if ($data->hasMorePages())
     <a href="{{ $data->nextPageUrl() }}">Next</a>
@endif

Add above code in view在视图中添加以上代码

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM