首頁  >  文章  >  php框架  >  關於 Laravel 專案 偽靜態分頁處理

關於 Laravel 專案 偽靜態分頁處理

藏色散人
藏色散人轉載
2021-02-20 17:27:273247瀏覽
##上對「

手上有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

方法,然後傳遞每頁的頁碼。

paginate 方法會呼叫

Illuminate\Database\Concerns\BuildsQueries
    下的
  • paginator方法。 paginator 方法會建構一個 Illuminate\Pagination\LengthAwarePaginator
  • 的實例。
  • Illuminate\Pagination\LengthAwarePaginator 會使用 Illuminate\Pagination\AbstractPaginator
  • 中的
  • url方法進行建構請求參數和url。 現在我們找到產生 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中,我們需要的是參數還是放到位址中。

取得到所有的query 參數

判斷需要分頁的頁面路由中是否有綁定的路由參數

    如果沒有的話,我們就走Laravel 本身的分頁
  • 如果有的話,我們就透過路由和路由參數進行建構位址,並把它從query 參數中剔除
  • 判斷下目前的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.com。如有侵權,請聯絡admin@php.cn刪除