手上有Laravel 的項目,要求做偽靜態處理,項目中使用了Laravel 自帶的分頁組件,分頁組件分頁會在你的URL 用Query 的方式做頁碼的傳遞,達不到偽靜態的要求。
想要的效果對應Laravel 的路由是:我們偽靜態想要的效果大體是這樣的:
/software/3dmax/created_at/page-1.html
/software/{category}/{order}/page-{page}.html
/software/3dmax/created_at/page-1.html?category=3dmax&order=created_at&page=2這不是我們需要的,所以我們需要對Laravel 自帶的分頁元件進行修改。 Laravel 分頁元件在 Laravel 中我們如果需要分頁,會呼叫 模型中的
paginate
方法,然後傳遞每頁的頁碼。paginate
方法會呼叫
方法。
paginator 方法會建構一個
Illuminate\Pagination\LengthAwarePaginator
Illuminate\Pagination\LengthAwarePaginator 會使用
Illuminate\Pagination\AbstractPaginator方法進行建構請求參數和url。
現在我們找到產生 URL 的地方了,我們需要做的就是在這裡修改。
重寫分頁元件mkdir app/Pagination touch 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中,我們需要的是參數還是放到位址中。
判斷需要分頁的頁面路由中是否有綁定的路由參數
... 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(); } ...
paginate
方法,但是Illuminate\Database\Eloquent\Builder下,如果我們需要重寫的話,會很麻煩,並且還有一個問題就是,並不是我們所有的分頁都是需要偽靜態的,例如我們用戶中心的資料可能不太需要偽靜態。所以我們需要一個可以手動設定的東西,Larave 模型中有一個本地作用域,我們可以寫一個方法
staticPaginate,當需要使用靜態分頁的時候,我們可以
Model->query ()->staticPaginate(); 來調用,所需的參數和Laravel 自帶的
pageinage 方法類似。
公共的Model 基底類別檔案
Laravel專案中的Model 我們一般不會直接繼承
Illuminate\Database\Eloquent\Model
在模型中定義本地作用域
你只需要拷貝
Illuminate\Database\Eloquent\Builder
$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中文網其他相關文章!