我们知道,Laravel 自带的分页器方法包含 simplePaginate 和 paginate 方法,一个返回不带页码的分页链接,另一个返回带页码的分页链接,但是这两种分页链接页码都是以带问号的动态参数形式附加在查询字符串中,形如 https://laravelacademy.org?page=100,但是这种包含动态参数的 URL 格式对 SEO 不友好,我们最好将其转化为 https://laravelacademy.org/page/100 这种不带问号的伪静态分页链接格式,遗憾的是 Laravel 并没有提供对这种伪静态分页链接格式的自定义支持,只好自己动手了。

我们将基于 paginate 方法实现的分页进行扩展,只是修改其分页链接格式,该方法底层调用了 Illuminate\Pagination\LengthAwarePaginator 类实现分页,所以我们需要自定义一个继承自该分页器类的 app/Utils/AcademyPaginator.php。

一、创建文件app/Utils/AcademyPaginator.php

<?php
namespace App\Utils; use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Support\Str;
use Illuminate\Pagination\Paginator;
use Illuminate\Pagination\LengthAwarePaginator as BasePaginator; class AcademyPaginator extends BasePaginator
{
/**
* 重写页面 URL 实现代码,去掉分页中的问号,实现伪静态链接
* @param int $page
* @return string
*/
public function url($page)
{
if ($page <= 0) {
$page = 1;
} // 移除路径尾部的/
$path = rtrim($this->path, '/'); // 如果路径中包含分页信息则正则替换页码,否则将页码信息追加到路径末尾
if (preg_match('/\/page\/\d+/', $path)) {
$path = preg_replace('/\/page\/\d+/', '/page/' . $page, $path);
} else {
$path .= '/page/' . $page;
}
$this->path = $path; if ($this->query) {
$url = $this->path . (Str::contains($this->path, '?') ? '&' : '?')
. http_build_query($this->query, '', '&')
. $this->buildFragment();
} elseif ($this->fragment) {
$url = $this->path . $this->buildFragment();
} else {
$url = $this->path;
} return $url;
} /**
* 重写当前页设置方法
*
* @param int $currentPage
* @param string $pageName
* @return int
*/
protected function setCurrentPage($currentPage, $pageName)
{
if (!$currentPage && preg_match('/\/page\/(\d+)/', $this->path, $matches)) {
$currentPage = $matches[1];
} return $this->isValidPageNumber($currentPage) ? (int) $currentPage : 1;
} /**
* 将新增的分页方法注册到查询构建器中,以便在模型实例上使用
* 注册方式:
* 在 AppServiceProvider 的 boot 方法中注册:AcademyPaginator::rejectIntoBuilder();
* 使用方式:
* 将之前代码中在模型实例上调用 paginate 方法改为调用 seoPaginate 方法即可:
* Article::where('status', 1)->seoPaginate(15, ['*'], 'page', page);
*/
public static function injectIntoBuilder()
{
/*
* $perPage 每页显示多少条
* $columns 查询的字段
* $pageName 翻页链接的参数名
* $page 当前页数
* */
Builder::macro('seoPaginate', function ($perPage, $columns, $pageName, $page) {
$perPage = $perPage ?: $this->model->getPerPage(); $items = ($total = $this->toBase()->getCountForPagination())
? $this->forPage($page, $perPage)->get($columns)
: $this->model->newCollection(); $options = [
'path' => Paginator::resolveCurrentPath(),
'pageName' => $pageName,
]; return Container::getInstance()->makeWith(AcademyPaginator::class, compact(
'items', 'total', 'perPage', 'page', 'options'
));
});
}
}

二、在 AppServiceProvider 的 boot 方法中全局调用这个注入:

// 为查询构建器注入自己实现的分页器方法
AcademyPaginator::injectIntoBuilder();

这样,在模型实例上调用 seoPaginate 方法,将通过 AcademyPaginator 进行分页。接下来,就可以在自己的代码中编写以下这种代码实现伪静态分页链接了:

$articles = Article::with('author', 'category')->public()->orderBy('id', 'desc')->seoPaginate($pageSize, $this->listColumns, 'page', $page);

参考文档:https://laravelacademy.org/post/9661.html

在 Laravel 中通过自定义分页器分页方法实现伪静态分页链接以利于 SEO的更多相关文章

  1. Laravel 中通过自定义分页器分页方法实现伪静态分页链接以利于 SEO

    我们知道,Laravel 自带的分页器方法包含 simplePaginate 和 paginate 方法,一个返回不带页码的分页链接,另一个返回带页码的分页链接,但是这两种分页链接页码都是以带问号的动 ...

  2. 详解如何在Laravel中增加自定义全局函数

    http://www.php.cn/php-weizijiaocheng-383928.html 如何在Laravel中增加自定义全局函数?在我们的应用里经常会有一些全局都可能会用的函数,我们应该怎么 ...

  3. django中的自定义分页器

    1.什么是自定义分页器 当我们需要在前端页面展示的数据太多的时候,我们总不能将数据展示在一页上面吧!这时,我们就需要自定义一个分页器,将数据分成特定的页数进行展示,每一页展示固定条数的数据! 2.为什 ...

  4. Javascript 中创建自定义对象的方法(设计模式)

    Javascript 中创建对象,可以有很多种方法. Object构造函数/对象字面量: 抛开设计模式不谈,使用最基本的方法,就是先调用Object构造函数创建一个对象,然后给对象添加属性. var ...

  5. php在laravel中使用自定义的Common类

    众所周知,laravel是一款高度集成的开发框架,框架内置非常多的操作方法,从而保证了我们的开发效率.但是在日常中为了满足我们的个性化业务,也需要自己去编写工具类,在laravel中我们完成编写后还需 ...

  6. JavaScript中创建自定义对象的方法

    本文内容参考JavaScript高级程序设计(第3版)第6章:面向对象的程序设计 ECMA-262中把对象定义为:“无序属性的集合,其属性可以包含基本值.对象或者函数.”我所理解的就是对象就是一个结构 ...

  7. Laravel中利用队列发送邮件的方法示例

    https://www.jb51.net/article/121647.htm 本文主要给大家介绍了关于Laravel中队列发送邮件的相关内容,分享出来供大家参考学习,下面话不多说了,来一起看看详细的 ...

  8. delphi中使用自定义资源的方法

    如果要在delphi中使用自定义资源文件*.res文件,比如一个光标,此时可以采用下列步骤: 1,创建包含相应的资源文件,这里是创建一个包含自定义光标的res文件. 2,在主窗体的pas文件中加入编译 ...

  9. 纯JS前端分页方法(JS分页)

    1.JS分页函数:开发过程中,分页功能一般是后台提供接口,前端只要传page(当前页码)和pageSize(每页最大显示条数)及对应的其他查询条件,就可以返回所需分页显示的数据. 但是有时也需要前端本 ...

随机推荐

  1. MFC文档视图中窗口切换 (2012-05-11 18:32:48)

    在文档试图应用程序,有时需要在工作区切换试图,以下就是如何切换试图了 .创建要切换的视图类,同时把构造函数,Create函数改变为public .在需要切换试图的动作响应中,加入切换代码,一般是在CM ...

  2. 简单的Linq查询语句

    下面我来我大家介绍几种简单的查询方式. 1.简单语法 这个LINQ语句的第一个关键字是from,from后面加的是范围变量,范围变量后加in,后加上事先实例化的模型,然后点出数据的来源. List是列 ...

  3. Bash 脚本编程的一些高级用法

    概述 偶然间发现 man bash 上其实详细讲解了 shell 编程的语法,包括一些很少用却很实用的高级语法.就像发现了宝藏的孩子,兴奋莫名.于是参考man bash,结合自己的理解,整理出了这篇文 ...

  4. I/O模式及select、 poll、 epoll

    I/O多路复用技术 复用技术(multiplexing)并不是新技术而是一种设计思想,在通信和硬件设计中存在频分复用.时分复用.波分复用.码分复用等.在日常生活中复用的场景也非常多.从本质上来说,复用 ...

  5. C++ 半同步半异步的任务队列

    代码已发布至 HAsyncTaskQueue

  6. 小熊派4G开发板初体验

    开发板硬件资源介绍 前阵子小熊派发布了一款超高性价比的4G开发板(19.8元包邮),但是板子仅限量1000套.小熊派官方给我送了一块,我们一起来学习学习: 板子做得小巧精致,控制核心用的是移远的EC1 ...

  7. BZOJ 1131 [POI2008] STA-Station 题解

    题目 The first stage of train system reform (that has been described in the problem Railways of the th ...

  8. 上海python14期第一次周考

    上海python14期第一次周考 1 介绍 满分50分 考试范围: Python语法 数据类型 流程控制 考试时间: 周五下午3.00点-晚6:00 2 基础题(38分) 什么是编程语言?什么是语言? ...

  9. 本地缓存解决方案-Caffeine Cache

    1.1 关于Caffeine Cache ​ Google Guava Cache是一种非常优秀本地缓存解决方案,提供了基于容量,时间和引用的缓存回收方式.基于容量的方式内部实现采用LRU算法,基于引 ...

  10. 全局作用域中,用 const 和 let 声明的变量不在 window 上,那到底在哪里?如何去获取?

    在ES5中,顶层对象的属性和全局变量是等价的,var 命令和 function 命令声明的全局变量,自然也是顶层对象. var a = 12; function f(){}; console.log( ...