튜토리얼 칼럼에서 소개한 내용입니다. 도움이 필요한 친구들에게 도움이 되길 바랍니다! 저는 의사 정적 처리가 필요한 Laravel 프로젝트를 가지고 있습니다. 이 프로젝트는 Laravel의 자체 페이징 구성 요소를 사용하여 의사 정적 처리 요구 사항을 충족할 수 없는 URL의 페이지 번호를 전달합니다.
원하는 효과pseudo-static에 대해 원하는 효과는 대략 다음과 같습니다:
/software/3dmax/created_at/page-1.html
/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 Pagination Component
Laravel에서는 페이지 매김이 필요한 경우 모델에서 paginate
메소드를 호출한 다음 각 페이지의 페이지 번호를 전달합니다.
paginate
메서드는 IlluminateDatabaseConcernsBuildsQueries
아래의 paginator
메서드를 호출합니다. paginator
메소드는 IlluminatePaginationLengthAwarePaginator
의 인스턴스를 생성합니다. IlluminatePaginationLengthAwarePaginator
는 IlluminatePaginationAbstractPaginator
의 url
메서드를 사용하여 요청 매개변수와 URL을 구성합니다. 페이징 구성 요소 다시 작성paginate
方法,然后传递每页的页码。
paginate
方法会调用 IlluminateDatabaseConcernsBuildsQueries
下的paginator
方法。paginator
方法会构造一个 IlluminatePaginationLengthAwarePaginator
的实例。IlluminatePaginationLengthAwarePaginator
会使用 IlluminatePaginationAbstractPaginator
中的url
方法进行构造请求参数和url。现在我们找到生成 URL 的地方了,我们需要做的就是在这里修改。
Laravel 中本身支持自定义分页组件,But 我们做的不是自定义分页,我们需要对于方法进行重写。
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 { }
首先 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
方法的定义在IlluminateDatabaseEloquentBuilder
下,如果我们需要重写的话,会很麻烦,并且还有一个问题就是,并不是我们所有的分页都是需要伪静态的,比如我们用户中心的数据可能不太需要伪静态。所以我们需要一个可以手动设置的东西,Larave 模型中有一个 本地作用域,我们可以写一个方法staticPaginate
,当需要使用静态分页的时候,我们可以Model->query()->staticPaginate();
来调用,所需要的参数和 Laravel 自带的 pageinage
方法类似。
Laravel项目中的 Model 我们一般不会直接继承IlluminateDatabaseEloquentModel
我们一般都在 appModels
目录定义一个 Model 基类,所有的模型都继承自 Model 基类,这并不是必须的,只是这样的话对于模型修改,或添加公共的方法比较方便。
你只需要拷贝 IlluminateDatabaseEloquentBuilder
下的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);
paginate
를 호출합니다. model code> 메서드를 사용하지만 paginate
메서드는 IlluminateDatabaseEloquentBuilder
아래에 정의되어 있습니다. 이를 다시 작성해야 한다면 매우 번거로울 것이며 또 다른 문제는 우리 모두가 그렇지 않다는 것입니다. 페이징에는 의사 정적이 필요합니다. 예를 들어 사용자 센터의 데이터에는 의사 정적이 필요하지 않을 수 있습니다. 따라서 수동으로 설정할 수 있는 것이 필요합니다. Larave 모델에는 staticPaginate
메서드를 작성할 수 있습니다. 정적 페이지 매김을 사용해야 하는 경우 Model->를 수행할 수 있습니다. ; query()->staticPaginate();
를 호출하는 데 필요한 매개변수는 Laravel의 자체 pageinage
메소드와 유사합니다. 🎜🎜Public Model 기본 클래스 파일🎜🎜Laravel 프로젝트의 모델 우리는 일반적으로 IlluminateDatabaseEloquentModel
을 직접 상속하지 않습니다. 우리는 일반적으로 appModels
디렉토리에 Model 기본 클래스를 정의합니다. Model 기본 클래스에서 상속합니다. 필수는 아니지만 모델을 수정하거나 공용 메서드를 추가하는 것이 더 편리합니다. 🎜🎜모델에서 로컬 범위를 정의하세요🎜🎜IlluminateDatabaseEloquentBuilder
에서 paginate
메서드의 내용을 복사하고 $this
의 포인터를 수정하기만 하면 됩니다. > 그게 다입니다🎜rrreee🎜커스텀 페이징 구성 요소 교체🎜rrreee🎜프로젝트에서 정적 페이징 구성 요소 사용🎜rrreee위 내용은 Laravel 프로젝트 의사 정적 페이징 처리 정보의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!