使用Laravel分页功能限制显示的链接数量。

44
有没有简单的方法来限制Laravel分页显示的链接数量?
目前最多显示13个链接(Prev, 1 2 3 4 5 7 8 .. 78 79 next)
然而,这对于移动设备来说太多了,导航变成了两行...有没有办法将链接设置为只显示10个?
我已经尝试过调整分页显示器,但似乎没有任何实际效果。

请查看http://forumsarchive.laravel.io/viewtopic.php?id=1411。 - Hmmm
15个回答

33

我使用CSS来限制允许的链接。非常简单... 可以扩展到显示任意数量的页面,在任意数量的断点处。

@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;
    }
}

这种特定的实现允许箭头,'...',第一页,活动页和最后一页。


2
谢谢!您的答案加上 https://developer.mozilla.org/en-US/docs/Web/CSS/Adjacent_sibling_combinator 就是我要找的。 - Ryan
2
这是一种好方法,因为我想在桌面视图上保留更多的页面链接,并仅限制移动端。 - regularmike
1
这是一个很好的解决方案。它适用于 Laravel 8,该版本现在支持 onEachSide 方法,但即使将其设置为 1,在移动设备上仍然不足够。我能看到这个答案唯一的问题是当你在第四页时,它不会显示左边的省略号。在这种情况下,它会显示:1、2、4、...、19、20。这是因为 Laravel 生成代码的方式。 - Luis Rodriguez
1
如果您想显示活动页面之后的下一个数字,请将“.page-item.active + li”添加到选择器列表中。 - andychukse
1
如果我们想在当前页之前显示上一页的链接编号,那么该怎么做呢?@andychukse - Harsh Patel
显示剩余4条评论

29

现在Laravel 5.7有一种新的分页方法,可以自定义分页器两侧的链接数量。由于这种新方法,某些情况下您不再需要自定义分页视图。以下是您可以使用的API来定义当前页面两侧的链接计数:

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

在你的控制器上编写该代码。

你可以在https://laravel-news.com/laravel-5-7-pagination-link-customizations上查看更多详细信息。


2
在 Laravel 6 中似乎不按预期工作 https://stackoverflow.com/questions/58521413/fit-pagination-on-mobile-devices-laravel-bootstrap - calin24
1
谢谢! 对我有用。 我写了这个: $blog = Blog::where('type', "news")->latest('created_at')->paginate(5)->onEachSide(1); 我使用了 onEachSide(1)。这使得链接保持在每个设备的宽度上。 - Raihanul Alam Hridoy
1
@calin24 当我在 Laravel 6 中使用 $collection->render() 时,它对我无效,但是当我使用 $collection->onEachSide(1)->links() 时有效。 - dsturbid
1
我在Laravel 8 Bootstrap分页中使用了 {{ $detail_data->onEachSide(3)->links() }},但它没有起作用。它显示超过15个页面链接按钮。请帮助我解决这个问题。我参考了 https://laravel.com/docs/8.x/pagination#adjusting-the-pagination-link-window 官方文档。 - Harsh Patel
@HarshPatel,如果您打开一个新的stackoverflow问题并展示相关代码,也许回答会更容易 :) - Abid Khairy

17

来自laravel 8文档。如果需要,您可以使用blade中的onEachSide方法来控制在当前页面两侧显示多少个附加链接:

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

13

适用于 Laravel 5.6 及以上版本:

发布供应商模板:

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

请按以下方式编辑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

这个示例以正确的方式处理了新的CSS类、活动链接、三个点(正确地,而不是1..2 3 4)并且可定制(您想显示的页面数量)。

示例

三个点被正确处理


6

我创建了一个新的自定义 Presenter,仅显示 10 个链接。它包括以下 3 个步骤:

1. 创建您自己的自定义 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();
        }
    }

} 

创建自己的分页视图(例如custom-paginator.php),将其放置在您的视图文件夹中

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

请更新您的 app/config.view.php 文件。

'pagination' => 'custom-paginator',

通过以下更改,您将能够获得一个包含10个链接的分页器。
希望这能帮到您 :D

1
感谢Henrik和hakre的反馈,我已经更新了我的答案并提供了示例答案。将来会改进我的回答方式:D 我想发布一张图片截图,但是声望不够 >_< - Zesky

4
在视图文件夹中创建一个名为pagination的新文件夹,并在其中创建一个名为default.blade.php的文件,代码如下。这意味着您已经用我们的新分页文件覆盖了核心分页文件。这将在分页链接中设置一些限制。
@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

如果你想要分页,那么你需要调用Laravel的分页函数,并使用这个视图文件参数。

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

3
我知道这是一个老问题,但仍然没有办法在使用函数links()参数时进行设置。我编写了一个简单的jQuery代码,也许它可以帮助某些人。它比Zesky的答案简单得多。我不是说更好,只是更简单 :)
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:

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

这段代码仅显示少数几个li元素,包括活动元素、前面两个元素、后面两个元素以及上一个/下一个箭头。最多只显示7个可见的元素,而不是15个。

谢谢提供示例。但是这在异步分页上不起作用。 - user2094178
最佳选择是制作自己的分页视图:https://dev59.com/El4c5IYBdhLWcg3wLXka#44845954 - Mooncake

2

在 Laravel 5.3+ 中,旧的自定义 presenter 定义方式已经不再适用。现在,Illuminate/Pagination/UrlWindow::make() 方法中的 $onEachSide 参数似乎是硬编码了要显示的链接数:

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

最终我只是写了自己的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();
    }
}

我们使用Twig,因此我将其注册为Twig过滤器。我想类似的事情也可以在Blade上完成。

这是正确的答案,除了在Laravel 5.6中,默认变量$onEachSide = 3位于Illuminate\Pagination\UrlWindow::get($onEachSide = 3){ // }。它也可以在Illuminate\Pagination\LengthAwarePaginator::elements()函数中设置,在该函数中调用为$window = UrlWindow::make($this);,只需像这样传递第二个变量$window = UrlWindow::make($this, 1); - Matthew Mathieson
@barryp - 你能否提供一个示例文件并提供更多信息吗?对于初学者来说,这个答案非常难以理解。 - K M
@KM - 这个示例是针对一个较旧版本的Laravel,现在并不适用。请参见下面的答案,其中使用了paginator的onEachSide(n)方法。 - barryp
@barryp - 我正在寻找一个较旧版本的Laravel的解决方案。 - K M

1

这是一个老问题,但我想分享一下我最近如何在Laravel 5.2应用程序中减少分页链接数量的方法:

在你的ViewServiceProvider中:

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

App\Pagination\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);
    }
}

来自:

enter image description here

致:

enter image description here


1
这是一个较旧的问题,但是这里的回答都没有更新到最新的 Laravel 文档。对于较新版本的 Laravel(Laravel 5.6+),有一种比较容易的解决方法,但需要发布供应商分页视图,如Laravel文档所述。假设您还没有发布或更改默认分页视图,则运行的命令为:
php artisan vendor:publish --tag=laravel-pagination

一旦视图被发布,您将在resources/views/vendor/pagination目录中找到bootstrap-4.blade.php文件。 您可以编辑此文件并使分页链接以您想要的方式显示。 为了减少默认显示的链接数量,我只是使用了一点内联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

大部分的代码都在bootstrap-4.blade.php默认的视图中,但我添加了$index=0, $index<4, $index++的代码来限制分页器左侧链接的数量为4个。
这是Laravel文档中处理此问题的正确方式,无需编辑composer供应商文件或尝试以其他方式入侵系统。我确实意识到JR Lawhorne发布了类似的答案,但它不包括发布供应商文件的整个过程。希望这对其他人有所帮助。

这比onEachSide(1)好一点。 - Freddy Daniel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接