Laravel强大的路由功能使其url不管是对搜索引擎还是用户都是非常的友好,但美中不足的是它的分页默认url却是带参数查询的(http://www.lara.com/posts?page=2),这让做惯了seo的我心里总感觉有点别扭。

为了看着顺眼点,决定动手对它改造一下,首先要了解它的工作原理,打开分页器的服务提供者PaginationServiceProvider.php,查看源代码:

<?php

namespace Illuminate\Pagination;

use Illuminate\Support\ServiceProvider;

class PaginationServiceProvider extends ServiceProvider
{
    /**
     * Register the service provider.
     *
     * @return void
     */
    public function register()
    {
        Paginator::currentPathResolver(function () {
            return $this->app['request']->url();
        });

        Paginator::currentPageResolver(function ($pageName = 'page') {
            return $this->app['request']->input($pageName);
        });
    }
}

register方法中发现,laravel分页器使用http request对象中的page参数值作为当前页码,而page的值是通过GET方式获取的,而形如http://www.lara.com/posts/page/2url中没有任何GET参数。既然不能通过静态url不能传入page参数,我们就手工注入。在路由中,使用request对象的merge方法将page参数添加进去。

Route::get('posts/page/{page?}', function ($page = 1) {
    Request::merge(['page' => $page]);
    $posts = Post::orderBy('id', 'DESC')->paginate(3);

    return view('post.index', ['posts' => $posts]);
});

访问http://www.lara.com/posts/page/2

laravel分页链接

路由修改完后,能够获取正确的分页数据,但点击下面的分页链接发现url变成www.lara.com/posts/page/2/?page=5这种形式了,看起来是访问第5页的数据,但出来的还是第2页的,这是因为通过GET方式,request获取了page=5,但通过路由我们又手工向request里面添加了page=2,导致后面的页码2把原来的5覆盖了。为了既能得到我们想要的静态url,又能得到正确的分页数据,我们对视图中的render方法进行处理:

{!! preg_replace("~(/page/\d+)?\?page=~", '/page/', $posts->render()) !!}

分页url静态化

修改完后,分页的静态url访问和显示就都成功了。