laravel分页伪静态化

调用分页

$data = Product::query()->paginate(100);

我们将基于 paginate 方法实现的分页进行扩展,只是修改其分页链接格式,该方法底层调用了 Illuminate\Pagination\LengthAwarePaginator 类实现分页,所以我们需要自定义一个继承自该分页器类的 app/Utils/AcademyPaginator.php,初始化代码如下:
我们要求分页格式是ProductNameList_关键字_页码

<?php
namespace app/Utils;

use Illuminate\Container\Container;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Pagination\LengthAwarePaginator;
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('/\/search_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE)){
            preg_match('/\/search_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE);
            $path_arr = explode('_',$matches[0][0]);
            $url = preg_replace('/\/search_[\s\S]*_\d+/', '/search_'.$path_arr[1].'_' . $page, $path);
        }else if( preg_match('/\/supplierList_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE)){
            preg_match('/\/supplierList_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE);
            $path_arr = explode('_',$matches[0][0]);
            $url = preg_replace('/\/supplierList_[\s\S]*_\d+/', '/supplierList_'.$path_arr[1].'_' . $page, $path);
        }else if( preg_match('/\/productCasList_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE)){
            preg_match('/\/productCasList_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE);
            $path_arr = explode('_',$matches[0][0]);
            $url = preg_replace('/\/productCasList_[\s\S]*_\d+/', '/productCasList_'.$path_arr[1].'_' . $page, $path);
        }else if( preg_match('/\/productNameList_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE)){
            preg_match('/\/productNameList_[\s\S]*_\d+/',$path,$matches,PREG_OFFSET_CAPTURE);
            $path_arr = explode('_',$matches[0][0]);
            $url = preg_replace('/\/productNameList_[\s\S]*_\d+/', '/productNameList_'.$path_arr[1].'_' . $page, $path);
        }else{
            $url = '';
        }

//        // 如果路径中包含分页信息则正则替换页码,否则将页码信息追加到路径末尾
//        dd($this->query);
//        if (preg_match('/\/search_[\s\S]*_\d+/', $path)) {
//            $path = preg_replace('/\/search_[\s\S]*_\d+/', '/search_[\s\S]*_' . $page, $path);
//        } else {
//            $path .= '/search_' . $page;
//        }
//        $this->path = $path;
//
//        if ($this->query) {
//            $this_path_arr = explode('_',$this->path);
//            $path = $this_path_arr[0];
//            foreach($this->query as $val){
//                $path .= '_'.$val;
//            }
//            $url = $path.'_'.$this_path_arr[1].$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 方法即可:
     */
    public static function injectIntoBuilder()
    {
        \Laravel\Scout\Builder::macro('seoPaginate', function ($perPage,$currentPage=1,$pageName='page') {
            $perPage = $perPage ?: $this->model->getPerPage();
            $engine = $this->engine();
            $items = $this->model->newCollection($engine->map(
                $this, $rawResults = $engine->paginate($this, $perPage, $currentPage), $this->model
            )->all());
            $options = [
                'path' => Paginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ];
            $total =  $this->getTotalCount($rawResults);
            return Container::getInstance()->makeWith(AcademyPaginator::class, compact(
                'items', 'total', 'perPage', 'currentPage', 'options'
            ));
        });
    }
}

这样,在模型实例上调用 seoPaginate 方法,将通过 AcademyPaginator 进行分页,最后我们在 AppServiceProvider 的 boot 方法中全局调用这个注入:

AcademyPaginator::injectIntoBuilder();

接下来,就可以在自己的代码中编写以下这种代码实现伪静态分页链接了:

$data = Product::query()->seoPaginate(100,$page);

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值