Home  >  Article  >  PHP Framework  >  About Laravel project pseudo-static paging processing

About Laravel project pseudo-static paging processing

藏色散人
藏色散人forward
2021-02-20 17:27:273255browse

The following is the Laravel tutorial column to introduce to you the Laravel project pseudo-static paging processing, I hope it will be helpful to friends in need!

I have a Laravel project that requires pseudo-static processing. The project uses Laravel's own paging component. The paging component will use Query to pass the page number in your URL. , failing to meet the pseudo-static requirements.

The desired effect

The effect we want for pseudo-static is roughly like this:

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

The route corresponding to Laravel is:

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

Because Laravel routing itself supports routing parameters, there is no problem in obtaining our variables. However, Laravel's own paging component will pass your parameters using Query, so the generated paging address is as follows Kind of

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

This is not what we need, so we need to modify Laravel's own paging component.

Laravel Pagination Component

In Laravel, if we need pagination, we will call the paginate method in the model, and then pass the page number of each page. The

  • paginate method will call the paginator method under Illuminate\Database\Concerns\BuildsQueries. The
  • paginator method will construct an instance of Illuminate\Pagination\LengthAwarePaginator.
  • Illuminate\Pagination\LengthAwarePaginator will use the url method in Illuminate\Pagination\AbstractPaginator to construct the request parameters and url.

Now that we have found the place where the URL is generated, all we need to do is modify it here.

Rewrite the paging component

Laravel itself supports custom paging components, but what we are doing is not custom paging, we need to rewrite the method.

Create LengthAwarePaginator class

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

File app/Pagination/LengthAwarePaginator.php Content:

<?php

namespace App\Pagination;

use Illuminate\Support\Arr;
use Illuminate\Support\Str;
use Illuminate\Pagination\LengthAwarePaginator as BasePaginator;

class LengthAwarePaginator extends BasePaginator
{
}

Rewrite Url method

First of all, Laravel’s own paging will Put the parameters in the route into Query. What we need is the parameters or put them into the address.

  • Get all query parameters
  • Determine whether there are bound routing parameters in the page route that needs to be paginated
  • If not, we will use Laravel itself Paging
  • If there is one, we will build the address through routing and routing parameters, and remove it from the query parameters
  • Judge whether there are any parameters in the current query parameters. If anything, we are the same as before.

Modify the content under 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();
    }

    ...

Use custom paging component

In Laravel, if we need paging, we will call the model The paginate method in , but the paginate method is defined under Illuminate\Database\Eloquent\Builder. If we need to rewrite it, it will be very troublesome, and Another problem is that not all of our paging needs to be pseudo-static. For example, the data in our user center may not need pseudo-static. So we need something that can be set manually. There is a local scope in the Larave model. We can write a method staticPaginate. When we need to use static pagination, we can Model->query ()->staticPaginate(); to call, the parameters required are similar to the pageinage method that comes with Laravel.

Public Model base class file

We generally do not directly inherit the Model in the Laravel projectIlluminate\Database\Eloquent\Model We usually use app The \Models directory defines a Model base class. All models inherit from the Model base class. This is not necessary, but it is more convenient to modify the model or add public methods.

Define the local scope in the model

You only need to copy the contents of the paginate method under Illuminate\Database\Eloquent\Builder and modify it Just point to $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,
        ]);
    }

    ...

Replace the custom paging component

# 替换
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'
        ));
    }

    ...

Use static paging component in the project

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

The above is the detailed content of About Laravel project pseudo-static paging processing. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete