• 技术文章 >php框架 >Laravel

    关于 Laravel 项目 伪静态分页处理

    藏色散人藏色散人2021-02-22 09:16:06转载306

    下面由Laravel教程栏目给大家介绍Laravel 项目 伪静态分页处理 ,希望对需要的朋友有所帮助!

    手上有个 Laravel 的项目,要求做伪静态处理,项目中使用了 Laravel 自带的分页组件,分页组件分页会在你的 URL 用 Query 的方式做页码的传递,达不到伪静态的要求。

    想要的效果

    我们伪静态想要的效果大体是这样的:

     /software/3dmax/created_at/page-1.html

    对应 Laravel 的路由是:

    /software/{category}/{order}/page-{page}.html

    因为 Laravel 路由本身是支持路由参数的,所以说 我们变量的获取是完全没有问题的,但是 Laravel 自带的分页组件会将你的 参数 用 Query 的方式做传递,所以生成的分页地址是下面这种

     /software/3dmax/created_at/page-1.html?category=3dmax&order=created_at&page=2

    这不是我们需要的,所以我们需要对 Laravel 自带的分页组件进行修改。

    Laravel 分页组件

    在 Laravel 中我们如果需要分页,会调用 模型中的 paginate 方法,然后传递每页的页码。

    现在我们找到生成 URL 的地方了,我们需要做的就是在这里修改。

    重写分页组件

    Laravel 中本身支持自定义分页组件,But 我们做的不是自定义分页,我们需要对于方法进行重写。

    创建 LengthAwarePaginator 类

    mkdir app/Pagination
    touch app/Pagination/LengthAwarePaginator.php

    文件 app/Pagination/LengthAwarePaginator.php 内容:

    <?php
    
    namespace App\Pagination;
    
    use Illuminate\Support\Arr;
    use Illuminate\Support\Str;
    use Illuminate\Pagination\LengthAwarePaginator as BasePaginator;
    
    class LengthAwarePaginator extends BasePaginator
    {
    }

    重写 Url 方法

    首先 Laravel 自带的分页 会把路由里面的参数放到 Query中,我们需要的是 参数还是放到地址中。

    修改 app/Pagination/LengthAwarePaginator.php下内容:

    ...
    
    public function url($page)
        {
            if ($page <= 0) {
                $page = 1;
            }
    
            $parameters = [$this->pageName => $page];
    
            if (count($this->query) > 0) {
                $parameters = array_merge($this->query, $parameters);
            }
    
            //判断的参数是否在 路由中 需要绑定的数据
            $params = \request()->route()->parameters();
    
            if (!empty($params)) {
                foreach ($parameters as $key => $parameter) {
                    if (isset($params[$key])) {
                        $params[$key] = $parameter;
                        unset($parameters[$key]);
                    }
                }
    
                $path = route(\request()->route()->getAction('as'), $params);
            } else {
                $path = $this->path;
            }
    
            // 判断是否有参数
            if (empty(Arr::query($parameters))) {
                return $path . $this->buildFragment();
            }
    
            return $path
                . (Str::contains($this->path, '?') ? '&' : '?')
                . Arr::query($parameters)
                . $this->buildFragment();
        }
    
        ...

    使用自定义的分页组件

    在 Laravel 中我们如果需要分页,会调用 模型中的 paginate 方法,但是paginate方法的定义在Illuminate\Database\Eloquent\Builder下,如果我们需要重写的话,会很麻烦,并且还有一个问题就是,并不是我们所有的分页都是需要伪静态的,比如我们用户中心的数据可能不太需要伪静态。所以我们需要一个可以手动设置的东西,Larave 模型中有一个 本地作用域,我们可以写一个方法staticPaginate,当需要使用静态分页的时候,我们可以Model->query()->staticPaginate(); 来调用,所需要的参数和 Laravel 自带的 pageinage 方法类似。

    公共的Model 基类文件

    Laravel项目中的 Model 我们一般不会直接继承Illuminate\Database\Eloquent\Model 我们一般都在 app\Models 目录定义一个 Model 基类,所有的模型都继承自 Model 基类,这并不是必须的,只是这样的话对于模型修改,或添加公共的方法比较方便。

    在模型中定义本地作用域

    你只需要拷贝 Illuminate\Database\Eloquent\Builder下的paginate方法的内容并修改$this的指向就可以了

    ...
    
    use Illuminate\Pagination\Paginator;
    # Laravel 自带的。
    use Illuminate\Contracts\Pagination\LengthAwarePaginator;
    
    ...
    
       /**
         * 自定义静态分页
         * @author kingofzihua
         * @param Builder $builder
         * @param int $perPage
         * @param array $columns
         * @param string $pageName
         * @param int|null $page
         * @return LengthAwarePaginator
         *
         * @throws \InvalidArgumentException
         */
        public function scopeStaticPaginate($builder, $perPage = null, $columns = ['*'], $pageName = 'page', $page = null)
        {
            if (request('page')) {
                request()->offsetSet('page', request('page'));
            }
    
            $page = $page ?: Paginator::resolveCurrentPage($pageName);
    
            $perPage = $perPage ?: $builder->getModel()->getPerPage();
    
            $results = ($total = $builder->toBase()->getCountForPagination())
                ? $builder->forPage($page, $perPage)->get($columns)
                : $builder->getModel()->newCollection();
            return $this->paginator($results, $total, $perPage, $page, [
                'path' => Paginator::resolveCurrentPath(),
                'pageName' => $pageName,
            ]);
        }
    
        ...

    替换自定义的分页组件

    # 替换
    use App\Pagination\LengthAwarePaginator;
    # --- use  Illuminate\Contracts\Pagination\LengthAwarePaginator;  // 注释
    
    ...
    
       /**
         *
         * @param \Illuminate\Support\Collection $items
         * @param int $total
         * @param int $perPage
         * @param int $currentPage
         * @param array $options
         * @return LengthAwarePaginator
         */
        protected function paginator($items, $total, $perPage, $currentPage, $options)
        {
            return Container::getInstance()->makeWith(LengthAwarePaginator::class, compact(
                'items', 'total', 'perPage', 'currentPage', 'options'
            ));
        }
    
        ...

    在项目中使用静态分页组件

    Model::query()->staticPaginate($pageSize);

    以上就是关于 Laravel 项目 伪静态分页处理的详细内容,更多请关注php中文网其它相关文章!

    本文转载于:learnku,如有侵犯,请联系a@php.cn删除
    专题推荐:laravel
    上一篇:关于Nacos解决laravel多环境下配置切换 下一篇:详解Laravel框架的核心架构
    第15期线上培训班

    相关文章推荐

    • 解决laravel上传图片之后目录有图片,但访问不到(404)的问题• 关于laravel自定义模板指令-tojs• 分享个人推荐的laravel或其它框架的编程规范• 详解Laravel之路由请求方式、路由传参• 关于Nacos解决laravel多环境下配置切换

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网