You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Yii2分页能否使用文章ID替代页码?附示例及代码

在Yii2分页中用文章ID替代页码的实现方案

是否可以在Yii2的分页功能中使用文章ID替代页码?例如,将分页请求参数从&page=2替换为&id=63。当前使用的分页控制器代码如下:

function actionIndex()
{
    $query = Article::find()->where(['status' => 1]);
    $countQuery = clone $query;
    $pages = new Pagination(['totalCount' => $countQuery->count()]);
    $models = $query->offset($pages->offset)
        ->limit($pages->limit)
        ->all();

    return $this->render('index', [
         'models' => $models,
         'pages' => $pages,
    ]);
}

视图代码如下:

foreach ($models as $model) {
    // display $model here
}

// display pagination
echo LinkPager::widget([
    'pagination' => $pages,
]);

完全可以实现,核心是放弃传统的offset分页逻辑,改用文章ID作为分页的分界点,以下是具体实现步骤:

一、修改控制器逻辑,处理id参数

不再依赖Pagination组件的偏移量计算,而是根据传入的id筛选数据,同时判断是否存在上/下一页:

use yii\helpers\Html;

function actionIndex()
{
    // 固定排序规则,这里以ID倒序为例(确保分页逻辑一致)
    $query = Article::find()->where(['status' => 1])->orderBy('id DESC');
    $lastId = Yii::$app->request->get('id');
    
    // 根据传入的id过滤数据:倒序时,下一页取比当前id更小的文章
    if ($lastId) {
        $query->andWhere(['<', 'id', $lastId]);
    }
    
    // 每页显示条数,可配置在params中
    $pageSize = Yii::$app->params['pageSize'] ?? 10;
    // 多查一条数据,用于判断是否有下一页
    $models = $query->limit($pageSize + 1)->all();
    
    $nextId = null;
    if (count($models) > $pageSize) {
        // 移除多查的那条数据,只保留当前页内容
        array_pop($models);
        // 下一页的请求id就是当前页最后一条文章的id
        $nextId = end($models)->id;
    }
    
    // 处理上一页的id:查询大于当前lastId的最后一组数据的第一条id
    $prevId = null;
    if ($lastId) {
        $prevModel = Article::find()
            ->where(['status' => 1])
            ->andWhere(['>', 'id', $lastId])
            ->orderBy('id DESC')
            ->limit($pageSize)
            ->one();
        if ($prevModel) {
            $prevId = $prevModel->id;
        }
    }
    
    return $this->render('index', [
        'models' => $models,
        'nextId' => $nextId,
        'prevId' => $prevId,
    ]);
}

二、修改视图,自定义分页链接

不再使用默认的LinkPager组件,手动生成带有id参数的分页链接:

foreach ($models as $model) {
    // 渲染文章内容
}

// 自定义分页栏
echo '<div class="pagination">';
if ($prevId) {
    echo Html::a('上一页', ['index', 'id' => $prevId], ['class' => 'page-link']);
}
if ($nextId) {
    echo Html::a('下一页', ['index', 'id' => $nextId], ['class' => 'page-link']);
}
echo '</div>';

注意事项

  • 必须固定排序规则(比如按ID正序/倒序),否则分页逻辑会出现混乱,用户可能看到重复或缺失的内容
  • 这种方案只适合简单的上/下一页场景,如果需要跳转到指定页码,该方案不适用(因为没有页码与ID的对应关系)
  • 如果页面有额外的筛选条件(比如分类、时间范围),需要将这些条件也附加到分页链接中,确保分页数据与筛选条件匹配

内容的提问来源于stack exchange,提问作者Bynd

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.02 17:45:29