Hyperf分页器:数据分页与分页样式定制

Hyperf分页器:数据分页与分页样式定制

【免费下载链接】hyperf 🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease. 【免费下载链接】hyperf 项目地址: https://gitcode.com/hyperf/hyperf

还在为海量数据的分页展示而烦恼?Hyperf分页器组件为您提供一站式解决方案,从基础分页到高级定制,让数据展示变得优雅而高效!

📋 读完本文您将获得

  • Hyperf分页器的核心概念与工作原理
  • 多种分页方式的实战代码示例
  • 分页样式深度定制技巧
  • 性能优化与最佳实践
  • 常见问题排查与解决方案

🚀 Hyperf分页器组件概述

Hyperf分页器是一个独立且强大的组件,专门用于处理数据分页需求。它提供了两种主要的分页器类型:

分页器类型特点适用场景
Paginator简单分页,不计算总数大数据量、性能敏感场景
LengthAwarePaginator完整分页,包含总数统计需要显示总页数的场景

核心架构设计

mermaid

🔧 安装与基础配置

安装分页器组件

composer require hyperf/paginator

基础使用示例

<?php

namespace App\Controller;

use Hyperf\HttpServer\Annotation\AutoController;
use Hyperf\HttpServer\Contract\RequestInterface;
use Hyperf\Paginator\Paginator;
use Hyperf\Collection\Collection;

#[AutoController]
class UserController
{
    public function index(RequestInterface $request)
    {
        $currentPage = (int) $request->input('page', 1);
        $perPage = (int) $request->input('per_page', 15);
        
        // 模拟数据集合
        $data = [
            ['id' => 1, 'name' => '张三', 'email' => 'zhangsan@example.com'],
            ['id' => 2, 'name' => '李四', 'email' => 'lisi@example.com'],
            // ... 更多数据
        ];
        
        $collection = new Collection($data);
        $pageData = array_values($collection->forPage($currentPage, $perPage)->toArray());
        
        return new Paginator($pageData, $perPage, $currentPage, [
            'path' => $request->getUri()->getPath()
        ]);
    }
}

📊 数据库分页实战

查询构造器分页

<?php

use Hyperf\DbConnection\Db;

class ProductController
{
    public function list()
    {
        $perPage = 20;
        
        // 基础分页查询
        $products = Db::table('products')
            ->where('status', 1)
            ->orderBy('created_at', 'desc')
            ->paginate($perPage);
            
        // 复杂条件分页
        $filteredProducts = Db::table('products')
            ->where('category_id', 1)
            ->where('price', '>', 100)
            ->where(function ($query) {
                $query->where('stock', '>', 0)
                      ->orWhere('is_preorder', 1);
            })
            ->paginate($perPage, ['*'], 'page', 2); // 指定页码
            
        return $products;
    }
}

模型分页

<?php

namespace App\Model;

use Hyperf\DbConnection\Model\Model;

class User extends Model
{
    protected $table = 'users';
}

class UserController
{
    public function index()
    {
        // 简单模型分页
        $users = User::paginate(15);
        
        // 带条件的分页
        $activeUsers = User::where('status', 'active')
            ->orderBy('last_login', 'desc')
            ->paginate(10);
            
        // 关联关系分页
        $usersWithPosts = User::with(['posts' => function ($query) {
            $query->where('published', true);
        }])->paginate(20);
        
        return $activeUsers;
    }
}

🎨 分页样式深度定制

自定义分页响应格式

<?php

namespace App\Service;

use Hyperf\Paginator\AbstractPaginator;
use Hyperf\Contract\Arrayable;

class CustomPaginator implements Arrayable
{
    protected AbstractPaginator $paginator;
    
    public function __construct(AbstractPaginator $paginator)
    {
        $this->paginator = $paginator;
    }
    
    public function toArray(): array
    {
        return [
            'meta' => [
                'current_page' => $this->paginator->currentPage(),
                'per_page' => $this->paginator->perPage(),
                'total' => method_exists($this->paginator, 'total') ? $this->paginator->total() : null,
                'last_page' => method_exists($this->paginator, 'lastPage') ? $this->paginator->lastPage() : null,
                'from' => $this->paginator->firstItem(),
                'to' => $this->paginator->lastItem(),
            ],
            'links' => [
                'first' => $this->paginator->url(1),
                'last' => method_exists($this->paginator, 'lastPage') ? $this->paginator->url($this->paginator->lastPage()) : null,
                'prev' => $this->paginator->previousPageUrl(),
                'next' => $this->paginator->nextPageUrl(),
            ],
            'data' => $this->paginator->items(),
        ];
    }
}

// 使用示例
$paginator = User::paginate(15);
$customResponse = new CustomPaginator($paginator);
return response()->json($customResponse->toArray());

分页URL定制

<?php

class ArticleController
{
    public function list(RequestInterface $request)
    {
        $articles = Article::paginate(10);
        
        // 自定义路径和参数
        $articles->withPath('/articles/list')
                 ->appends(['sort' => 'date', 'order' => 'desc']);
                 
        // 添加片段标识
        $articles->fragment('article-list');
        
        return $articles;
    }
}

分页链接数量控制

<?php

// 控制分页链接显示数量
$paginator = User::paginate(15);
$paginator->onEachSide(2); // 当前页左右各显示2个页码链接

// 生成自定义页码范围
$pageUrls = $paginator->getUrlRange(
    max(1, $paginator->currentPage() - 3),
    min($paginator->lastPage(), $paginator->currentPage() + 3)
);

⚡ 性能优化策略

大数据量分页优化

<?php

class BigDataController
{
    public function largeDataset()
    {
        // 使用简单分页避免COUNT查询
        $data = DB::table('large_table')
            ->orderBy('id')
            ->simplePaginate(100); // 使用simplePaginate避免总数计算
            
        // 使用游标分页(Cursor Pagination)
        $cursor = request()->input('cursor');
        $data = DB::table('large_table')
            ->orderBy('id')
            ->when($cursor, function ($query, $cursor) {
                return $query->where('id', '>', $cursor);
            })
            ->limit(100)
            ->get();
            
        return [
            'data' => $data,
            'next_cursor' => $data->last()?->id
        ];
    }
}

分页缓存策略

<?php

use Hyperf\Cache\Annotation\Cacheable;

class CachedController
{
    #[Cacheable(prefix: "users_page", ttl: 300)]
    public function cachedUsers($page = 1)
    {
        return User::paginate(15, ['*'], 'page', $page);
    }
    
    // 手动缓存分页结果
    public function manualCache()
    {
        $cacheKey = 'users_page_' . request()->input('page', 1);
        
        return cache()->remember($cacheKey, 300, function () {
            return User::with(['profile', 'roles'])
                ->orderBy('created_at', 'desc')
                ->paginate(15);
        });
    }
}

🔍 高级功能探索

自定义分页解析器

<?php

use Hyperf\Paginator\Paginator;

// 设置自定义当前页解析器
Paginator::currentPageResolver(function ($pageName = 'page') {
    return request()->input($pageName, 1);
});

// 设置自定义路径解析器
Paginator::currentPathResolver(function () {
    return request()->getUri()->getPath();
});

// 设置查询字符串解析器
Paginator::queryStringResolver(function () {
    return request()->getQueryParams();
});

分页器宏扩展

<?php

use Hyperf\Paginator\Paginator;
use Hyperf\Collection\Collection;

// 添加自定义方法到分页器
Paginator::macro('toCustomFormat', function () {
    return [
        'list' => $this->items(),
        'pagination' => [
            'current' => $this->currentPage(),
            'pageSize' => $this->perPage(),
            'total' => $this->total(),
        ]
    ];
});

// 使用自定义方法
$users = User::paginate(15);
return $users->toCustomFormat();

🛠️ 实战案例:电商商品分页

<?php

namespace App\Controller;

use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\GetMapping;
use App\Service\ProductService;

#[Controller(prefix: "/api/products")]
class ProductController
{
    public function __construct(private ProductService $productService) {}
    
    #[GetMapping("")]
    public function index()
    {
        $filters = [
            'category' => request()->input('category'),
            'price_min' => request()->input('price_min'),
            'price_max' => request()->input('price_max'),
            'sort' => request()->input('sort', 'created_at'),
            'order' => request()->input('order', 'desc'),
        ];
        
        $perPage = request()->input('per_page', 24);
        
        $products = $this->productService->getPaginatedProducts($filters, $perPage);
        
        // 定制分页响应
        return [
            'success' => true,
            'data' => [
                'products' => $products->items(),
                'pagination' => [
                    'current_page' => $products->currentPage(),
                    'per_page' => $products->perPage(),
                    'total' => $products->total(),
                    'total_pages' => $products->lastPage(),
                    'links' => [
                        'first' => $products->url(1),
                        'last' => $products->url($products->lastPage()),
                        'prev' => $products->previousPageUrl(),
                        'next' => $products->nextPageUrl(),
                    ]
                ],
                'filters' => $filters
            ]
        ];
    }
}

📝 最佳实践总结

分页器选择指南

场景推荐分页器理由
后台管理系统LengthAwarePaginator需要显示总数和总页数
移动端列表Paginator性能优先,避免COUNT查询
无限滚动自定义游标分页更好的用户体验
大数据量simplePaginate避免性能瓶颈

性能优化 checklist

  •  避免N+1查询问题
  •  合理使用索引加速分页
  •  考虑使用缓存分页结果
  •  大数据量时使用游标分页
  •  监控分页查询性能

常见问题解决方案

问题1:分页性能慢

// 解决方案:添加合适索引并优化查询
DB::table('users')->where('status', 1)->orderBy('created_at')->paginate(15);
// 确保 status 和 created_at 有复合索引

问题2:分页URL参数丢失

// 解决方案:使用withQueryString方法
$users = User::paginate(15)->withQueryString();

问题3:自定义分页参数名

// 解决方案:设置自定义页码参数名
$users = User::paginate(15, ['*'], 'p', request()->input('p'));

🎯 总结

Hyperf分页器提供了强大而灵活的分页解决方案,从简单的数组分页到复杂的数据库分页,都能轻松应对。通过本文的学习,您应该能够:

  1. 掌握Hyperf分页器的核心概念和使用方法
  2. 实现各种场景下的数据分页需求
  3. 深度定制分页样式和响应格式
  4. 优化分页性能并提供更好的用户体验
  5. 解决分页过程中的常见问题

分页不仅仅是技术实现,更是用户体验的重要组成部分。合理运用Hyperf分页器的各种特性,将为您的应用带来更加流畅和高效的数据展示体验。

点赞/收藏/关注三连,获取更多Hyperf实战技巧!下期预告:《Hyperf数据库优化:从入门到精通》

【免费下载链接】hyperf 🚀 A coroutine framework that focuses on hyperspeed and flexibility. Building microservice or middleware with ease. 【免费下载链接】hyperf 项目地址: https://gitcode.com/hyperf/hyperf

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值