thinkphp分页传递参数

99ANYc3cd6
预计阅读时长 28 分钟
位置: 首页 参数 正文

下面我将详细介绍几种主流且高效的方法,并给出代码示例。

thinkphp分页传递参数
(图片来源网络,侵删)

场景设定

假设我们有一个文章列表,需要根据 category_id(分类ID)和 keyword(搜索关键词)进行筛选,并支持按 order 字段排序。

我们的 URL 目标可能是这样的: http://your-app.com/article/index?page=2&category_id=5&keyword=ThinkPHP&order=hits


使用 paginate() 方法(推荐,ThinkPHP 5.1+)

这是最现代、最推荐的方法。paginate() 方法本身就可以接受一个数组参数,用于在生成分页时附加额外的查询条件。

控制器代码

在控制器中,你首先获取所有请求参数,然后将它们传递给 paginate() 方法。

thinkphp分页传递参数
(图片来源网络,侵删)
<?php
namespace app\controller;
use app\BaseController;
use app\model\Article; // 假设你有一个 Article 模型
class Article extends BaseController
{
    public function index()
    {
        // 1. 获取所有请求参数,包括 get, post 等
        $params = $this->request->param();
        // 2. 定义查询条件(从参数中提取,并进行安全过滤)
        $where = [];
        if (!empty($params['category_id'])) {
            $where[] = ['category_id', '=', intval($params['category_id'])];
        }
        if (!empty($params['keyword'])) {
            $where[] = ['title', 'like', '%' . trim($params['keyword']) . '%'];
        }
        // 3. 定义排序规则
        $order = !empty($params['order']) ? $params['order'] : 'id desc';
        // 4. 使用 paginate 进行分页查询
        // 第一个参数是每页显示条数,第二个参数是 'page',第三个参数是 where 条件
        // 注意:从 ThinkPHP 6.0 开始,paginate 的参数略有调整,但核心思想一致
        $list = Article::where($where)
                        ->order($order)
                        ->paginate([
                            'list_rows' => 10, // 每页10条
                            'page'       => $this->request->param('page', 1), // 获取页码,默认为1
                            'path'       => '', // 路径信息,留空自动获取
                            'query'      => $params, // 关键!将所有参数附加到分页链接的查询字符串中
                        ]);
        // 5. 将查询条件和参数传递给视图,以便在表单中保持状态
        $this->assign([
            'list'       => $list,
            'params'     => $params, // 传递所有参数
            'category_id' => $params['category_id'] ?? null,
            'keyword'    => $params['keyword'] ?? null,
            'order'      => $params['order'] ?? 'id desc',
        ]);
        return view();
    }
}

代码解析:

  • $this->request->param(): 获取所有请求参数,非常方便。
  • query => $params: 这是 核心paginate 方法的 query 参数接收一个数组,这些键值对会自动被附加到分页链接的 URL 后面。category_id=5keyword=ThinkPHP 就会自动加到 page=2 后面。
  • $params 或单独的变量传递给视图,是为了在页面的搜索表单中能回显用户之前输入的值,提升用户体验。

视图代码

在视图中,使用 {$list->render()} 来渲染分页链接。

<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">文章列表</title>
</head>
<body>
    <!-- 搜索表单 -->
    <form action="{:url('article/index')}" method="get">
        <input type="text" name="keyword" value="{$keyword|default=''}" placeholder="输入关键词搜索">
        <select name="category_id">
            <option value="">全部分类</option>
            <!-- 这里应该是动态加载的分类列表 -->
            <option value="5" {$category_id == 5 ? 'selected' : ''}>技术</option>
        </select>
        <select name="order">
            <option value="id desc" {$order == 'id desc' ? 'selected' : ''}>默认排序</option>
            <option value="hits desc" {$order == 'hits desc' ? 'selected' : ''}>按点击量</option>
        </select>
        <button type="submit">搜索</button>
    </form>
    <hr>
    <!-- 文章列表 -->
    {volist name="list" id="item"}
        <div>
            <h3>{$item.title}</h3>
            <p>{$item.content}</p>
        </div>
    {/volist}
    <!-- 分页链接 -->
    <div class="pagination">
        {$list->render()}
    </div>
</body>
</html>

当用户点击第二页时,{$list->render()} 生成的 HTML 链接会自动包含 category_idkeyword 等参数。


使用 buildPageUrl() 自定义分页链接(适用于 page 方法)

如果你使用的是传统的 page 方法(Article::where($where)->page($page, 10)->select()),它默认不提供 query 参数,这时,你可以通过自定义分页类来修改链接。

thinkphp分页传递参数
(图片来源网络,侵删)

创建自定义分页类

app\common 目录下创建 Page.php 文件。

<?php
// app\common\Page.php
namespace app\common;
use think\Paginator;
class Page extends Paginator
{
    /**
     * 附加的查询参数
     * @var array
     */
    protected $params = [];
    /**
     * 构造函数
     * @param array $items
     * @param int $perPage
     * @param int $currentPage
     * @param int $total
     * @param array $options
     */
    public function __construct(array $items, int $perPage, int $currentPage = 1, int $total = null, array $options = [])
    {
        parent::__construct($items, $perPage, $currentPage, $total, $options);
        // 从 options 中获取自定义参数
        $this->params = $options['params'] ?? [];
    }
    /**
     * 生成页码按钮
     * @param int $page
     * @return string
     */
    protected function appends($page)
    {
        // 合并自定义参数
        $appends = $this->params;
        $appends['page'] = $page;
        return $this->buildUrl($appends);
    }
    /**
     * 构建URL
     * @param array $params
     * @return string
     */
    protected function buildUrl(array $params = [])
    {
        if (empty($params)) {
            return $this->path;
        }
        $query = http_build_query($params);
        if ($this->fragment) {
            $this->path .= '#' . $this->fragment;
        }
        return $this->path . '?' . $query;
    }
}

在控制器中使用

// 在控制器中
public function index()
{
    $params = $this->request->param();
    // ... (where 条件和 order 排序的代码与方法一相同)
    // 使用 page 方法
    $page = $this->request->param('page', 1);
    $list = Article::where($where)->order($order)->page($page, 10)->select();
    // 获取总记录数
    $total = Article::where($where)->count();
    // 使用自定义分页类
    $pageObj = \app\common\Page::make($list, 10, $page, $total, [
        'path'   => $this->request->baseUrl(), // 当前URL路径
        'params' => $params, // 传递自定义参数
    ]);
    $this->assign([
        'list' => $pageObj,
        // ... 其他变量
    ]);
    return view();
}

视图代码

视图中的分页渲染部分与方法一完全相同: {$list->render()}


手动构建分页链接(不推荐,仅作了解)

这种方法最原始,不推荐在生产环境中使用,因为它维护成本高,容易出错,基本思路是:不使用 render(),而是用 for 循环手动生成所有页码链接。

<div class="pagination">
    {for $i=1;$i<=$list->lastPage();$i++}
        <a href="{:url('article/index', ['page'=>$i, 'category_id'=>$category_id, 'keyword'=>$keyword])}">{$i}</a>
    {/for}
</div>

缺点:

  • 代码冗长。
  • 如果参数很多,URL 构建会很麻烦。
  • 无法自动处理“上一页”、“下一页”、“首页”、“末页”等复杂逻辑。

总结与最佳实践

方法 优点 缺点 适用场景
paginate() + query 代码简洁,官方推荐,功能强大,自动处理所有逻辑 paginate 方法有依赖 强烈推荐,适用于所有 ThinkPHP 5.1+ 版本的项目
自定义分页类 灵活性高,可深度定制 需要额外创建文件,代码量稍多 仍在使用 page() 方法,或需要对分页进行高度定制化时
手动构建 无依赖,逻辑最直观 维护困难,代码冗余,功能不完善 学习理解分页原理,或极简单、不变化的分页场景

核心要点:

  1. 首选 paginate() 方法,它是最优雅的解决方案。
  2. 核心在于将所有需要传递的参数数组赋值给 paginate()query
  3. 在视图中,将参数传递给模板,以便在搜索表单等地方保持用户输入的状态,提升用户体验。
  4. 使用 {$list->render()} 来渲染分页导航,它会自动处理 query 参数。
-- 展开阅读全文 --
头像
adb shell命令参数有哪些常用选项?
« 上一篇 今天
ThinkPad L580参数有哪些?
下一篇 » 25分钟前

相关文章

取消
微信二维码
支付宝二维码

最近发表

标签列表

目录[+]