📜  自定义 laravel 分页链接 - PHP (1)

📅  最后修改于: 2023-12-03 15:27:43.802000             🧑  作者: Mango

自定义 Laravel 分页链接

简介

在 Laravel 中,我们可以使用 paginate() 方法来实现分页查询。当我们在 Blade 模板中使用这个方法生成的分页链接时,可能会发现链接的参数不太符合我们的需求(比如需要删除一些默认的参数)。在这个教程中,我们会介绍如何自定义 Laravel 的分页链接。

准备工作

在开始之前,我们需要先创建一个 Laravel 项目。我们可以使用以下命令来创建一个新的 Laravel 项目:

laravel new custom-pagination

然后,我们需要创建一个包含数据的模型,用于演示分页功能。我们可以使用以下命令来创建一个新的模型:

php artisan make:model Book -m

这个命令会同时生成一个迁移文件,我们可以在迁移文件中创建一些测试数据。以下是一个示例迁移文件,用于创建 books 表和一些测试数据:

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;

class CreateBooksTable extends Migration
{
    public function up()
    {
        Schema::create('books', function (Blueprint $table) {
            $table->id();
            $table->string('title');
            $table->string('author');
            $table->timestamps();
        });

        $data = [
            ['title' => 'Book 1', 'author' => 'Author 1'],
            ['title' => 'Book 2', 'author' => 'Author 2'],
            ['title' => 'Book 3', 'author' => 'Author 3'],
            ['title' => 'Book 4', 'author' => 'Author 4'],
            ['title' => 'Book 5', 'author' => 'Author 5'],
            ['title' => 'Book 6', 'author' => 'Author 6'],
            ['title' => 'Book 7', 'author' => 'Author 7'],
            ['title' => 'Book 8', 'author' => 'Author 8'],
            ['title' => 'Book 9', 'author' => 'Author 9'],
            ['title' => 'Book 10', 'author' => 'Author 10'],
            ['title' => 'Book 11', 'author' => 'Author 11'],
            ['title' => 'Book 12', 'author' => 'Author 12'],
            ['title' => 'Book 13', 'author' => 'Author 13'],
            ['title' => 'Book 14', 'author' => 'Author 14'],
            ['title' => 'Book 15', 'author' => 'Author 15'],
            ['title' => 'Book 16', 'author' => 'Author 16'],
            ['title' => 'Book 17', 'author' => 'Author 17'],
            ['title' => 'Book 18', 'author' => 'Author 18'],
            ['title' => 'Book 19', 'author' => 'Author 19'],
            ['title' => 'Book 20', 'author' => 'Author 20'],
        ];

        DB::table('books')->insert($data);
    }

    public function down()
    {
        Schema::dropIfExists('books');
    }
}

然后,我们需要运行迁移文件来创建表和测试数据:

php artisan migrate
生成分页链接

我们可以在 Controller 中使用 paginate() 方法来获取数据并生成分页链接。以下是一个示例 Controller,用于获取数据并在模板中渲染数据和分页链接:

namespace App\Http\Controllers;

use App\Models\Book;
use Illuminate\Http\Request;

class BookController extends Controller
{
    public function index(Request $request)
    {
        $books = Book::paginate(5);

        return view('books.index', compact('books'));
    }
}

在 Blade 模板中,我们可以使用 links() 方法来渲染分页链接。以下是一个示例模板,用于渲染数据和分页链接:

@foreach ($books as $book)
    <div>{{ $book->title }}</div>
    <div>{{ $book->author }}</div>
@endforeach

<div>{{ $books->links() }}</div>
自定义分页链接

默认情况下,Laravel 会在分页链接中包含一些参数,比如 pageper_page。我们可以使用 simplePaginate() 方法来生成不包含这些参数的分页链接,但是这个方法不会包含必要的参数,比如排序和筛选参数。

为了自定义 Laravel 的分页链接,我们需要继承 Illuminate\Pagination\LengthAwarePaginator 类,并重写 url() 方法。以下是一个示例类,用于自定义分页链接:

namespace App\Utils;

use Illuminate\Pagination\LengthAwarePaginator;

class CustomPaginator extends LengthAwarePaginator
{
    public function url($page)
    {
        $url = $this->path . '?page=' . $page;

        if (!empty($this->query)) {
            $url .= '&' . http_build_query($this->query);
        }

        return $url;
    }
}

在上面的示例中,我们重写了 url() 方法,将返回一个自定义的链接。我们在链接中包含了当前页数和查询参数,但是删除了默认的参数。

在 Controller 中,我们需要使用自定义的类来创建一个分页实例。以下是一个示例 Controller,用于使用自定义分页链接:

namespace App\Http\Controllers;

use App\Models\Book;
use App\Utils\CustomPaginator;
use Illuminate\Http\Request;

class BookController extends Controller
{
    public function index(Request $request)
    {
        $perPage = 5;
        $currentPage = $request->input('page', 1);
        $sortBy = $request->input('sort_by', 'id');
        $sortOrder = $request->input('sort_order', 'desc');

        $query = Book::query();
        $total = $query->count();
        $books = $query->orderBy($sortBy, $sortOrder)
            ->skip(($currentPage - 1) * $perPage)
            ->take($perPage)
            ->get();

        $paginator = new CustomPaginator($books, $total, $perPage, $currentPage, [
            'path' => $request->url(),
            'query' => $request->query(),
        ]);

        return view('books.index', compact('books', 'paginator'));
    }
}

在上面的示例中,我们首先获取当前页数和排序参数,然后使用 $query->count() 方法将查询到的总数保存到 $total 变量中。然后我们使用 $query->orderBy() 方法和 $query->skip()$query->take() 方法来获取当前页面的数据。

接着,我们使用自定义的 CustomPaginator 类来创建一个分页实例。我们向构造函数传递数据集合、总数、每页记录数、当前页数和一些配置参数。其中,path 参数表示当前链接,query 参数表示查询参数。

最后,我们将数据集合和分页实例传递给模板引擎,让模板引擎渲染数据和分页链接。以下是一个示例模板,用于渲染数据和分页链接:

<table>
    <thead>
        <tr>
            <th><a href="{{ request()->fullUrlWithQuery(['sort_by' => 'id', 'sort_order' => $sortOrder === 'asc' ? 'desc' : 'asc']) }}">ID</a></th>
            <th><a href="{{ request()->fullUrlWithQuery(['sort_by' => 'title', 'sort_order' => $sortOrder === 'asc' ? 'desc' : 'asc']) }}">Title</a></th>
            <th><a href="{{ request()->fullUrlWithQuery(['sort_by' => 'author', 'sort_order' => $sortOrder === 'asc' ? 'desc' : 'asc']) }}">Author</a></th>
        </tr>
    </thead>
    <tbody>
        @foreach ($books as $book)
            <tr>
                <td>{{ $book->id }}</td>
                <td>{{ $book->title }}</td>
                <td>{{ $book->author }}</td>
            </tr>
        @endforeach
    </tbody>
</table>

<div>{{ $paginator->links() }}</div>

在上面的示例中,我们使用了 request()->fullUrlWithQuery() 方法来生成包含排序参数的链接。这个方法会生成一个包含当前链接、查询参数和新排序参数的链接。我们还可以使用 request()->except() 方法来删除某些参数,让链接更加简洁。

总结

在本教程中,我们介绍了如何自定义 Laravel 的分页链接。我们首先使用 paginate() 方法和 links() 方法来生成默认的分页链接。然后,我们介绍了如何继承 Illuminate\Pagination\LengthAwarePaginator 类,并重写 url() 方法来生成自定义的分页链接。最后,我们给出了一个完整的示例,用于演示如何使用自定义分页链接。