首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 相關知識

Yii 分頁技術全解析:三種實現方式與最佳實踐

     編輯:PHP 相關知識

Yii 分頁技術全解析:三種實現方式與最佳實踐

分頁是 Web 應用處理大量資料的核心技術。Yi 提供了從底層 CPagination 到高階 CActiveDataProvider、內建 Widget 的完整分頁體系。本文詳細對比三種主流實現方式。

方式一:手動控制 CPagination(最靈活、適合複雜查詢)

控制器邏輯

public function actionIndex() {
    $criteria = new CDbCriteria();
    // 複雜查詢條件構建...
    
    $count = Article::model()->count($criteria);
    $pages = new CPagination($count);
    $pages->pageSize = 10;
    $pages->applyLimit($criteria); // 自動套用 LIMIT/OFFSET
    
    $models = Article::model()->findAll($criteria);
    
    $this->render('index', [
        'models' => $models,
        'pages' => $pages,
    ]);
}

視圖渲染

<?php foreach ($models as $model): ?>
    <div class="article">
        <h3><?php echo CHtml::encode($model->title); ?></h3>
        <p><?php echo CHtml::encode(mb_substr($model->content, 0, 200)); ?>...</p>
    </div>
<?php endforeach; ?>

<!-- 分頁導航 -->
<?php $this->widget('CLinkPager', [
    'pages' => $pages,
    'header' => '',
    'firstPageLabel' => '首頁',
    'lastPageLabel' => '末頁',
    'prevPageLabel' => '上一頁',
    'nextPageLabel' => '下一頁',
    'htmlOptions' => ['class' => 'pagination'],
]); ?>

方式二:CActiveDataProvider + CListView(標準 RESTful 列表)

控制器

public function actionIndex() {
    $dataProvider = new CActiveDataProvider('News', [
        'criteria' => [
            'condition' => 'status = 1',
            'order' => 'create_time DESC',
            'with' => ['author'], // 預載入關聯
        ],
        'pagination' => [
            'pageSize' => 20,
            'pageVar' => 'page', // URL 參數名
        ],
    ]);
    
    $this->render('index', ['dataProvider' => $dataProvider]);
}

視圖

<?php $this->widget('zii.widgets.CListView', [
    'dataProvider' => $dataProvider,
    'itemView' => '_view', // 渲染單筆資料的部分視圖
    'template' => "{items}\n{pager}",
    'emptyText' => '暫無新聞資料',
    'pager' => [
        'class' => 'CLinkPager',
        'header' => '',
        'cssFile' => false,
    ],
]); ?>

_view.php 部分視圖範例

<div class="news-item">
    <h4><?php echo CHtml::link(CHtml::encode($data->title), ['view', 'id' => $data->id]); ?></h4>
    <span class="meta">
        作者:<?php echo $data->author->name; ?> |
        時間:<?php echo date('Y-m-d', strtotime($data->create_time)); ?>
    </span>
    <p><?php echo CHtml::encode(mb_substr($data->content, 0, 150)); ?>...</p>
</div>

方式三:CGridView 管理後台表格(內建排序、篩選、分頁)

視圖完整配置

<?php $this->widget('zii.widgets.grid.CGridView', [
    'id' => 'news-grid',
    'dataProvider' => $model->search(),
    'filter' => $model, // 啟用欄位篩選
    'template' => "{items}\n{pager}",
    'pager' => [
        'class' => 'CLinkPager',
        'header' => '分頁:',
        'prevPageLabel' => '上一頁',
        'nextPageLabel' => '下一頁',
        'cssFile' => false,
    ],
    'summaryText' => '顯示 {start}-{end} 筆,共 {count} 筆',
    'columns' => [
        'id',
        [
            'name' => 'title',
            'htmlOptions' => ['width' => '30%'],
            'value' => 'mb_substr($data->title, 0, 30, "utf-8")',
        ],
        [
            'name' => 'content',
            'htmlOptions' => ['width' => '30%'],
            'value' => 'mb_substr(strip_tags($data->content), 0, 50, "utf-8")',
        ],
        [
            'name' => 'type',
            'value' => 'News::model()->getTypeLabel($data->type)',
            'filter' => News::model()->getTypeOptions(), // 下拉篩選
        ],
        'author.username', // 關聯欄位
        [
            'name' => 'status',
            'value' => 'News::model()->getStatusBadge($data->status)',
            'filter' => ['1' => '發布', '0' => '草稿', '-1' => '刪除'],
        ],
        [
            'class' => 'CButtonColumn',
            'template' => '{view} {update} {delete}',
            'buttons' => [
                'delete' => [
                    'label' => '移除',
                    'options' => ['class' => 'btn-delete', 'data-confirm' => '確定刪除?'],
                ],
            ],
        ],
    ],
]); ?>

模型 search() 方法標準實現

public function search() {
    $criteria = new CDbCriteria;
    $criteria->compare('id', $this->id);
    $criteria->compare('title', $this->title, true);
    $criteria->compare('content', $this->content, true);
    $criteria->compare('type', $this->type);
    $criteria->compare('user', $this->user, true);
    $criteria->compare('status', $this->status);
    $criteria->compare('create_data', $this->create_data, true);
    
    return new CActiveDataProvider($this, [
        'criteria' => $criteria,
        'pagination' => ['pageSize' => 50],
        'sort' => ['defaultOrder' => 'create_data DESC'],
    ]);
}

三種方式對比選型指南

維度CPagination 手動CActiveDataProvider + CListViewCGridView
適用場景複雜自定 SQL、多表 JOIN、非 ActiveRecord 查詢標準列表頁、RESTful API、前台展示後台管理、需排序/篩選/批次操作的表格
程式碼量最多中等最少(聲明式配置)
彈性最高中等受限於 GridView 架構
效能調校完全控制透過 criteria 優化需注意關聯查詢 N+1 問題
前端整合手工渲染部分視圖複用內建 AJAX 排序/分頁/篩選

進階優化技巧

1. 自定分頁 URL 規則

// urlManager 規則
'rules' => [
    'news/page/' => 'news/index',
    'news//page/' => 'news/category',
]

2. AJAX 無刷新分頁

// CListView / CGridView 啟用 AJAX
'ajaxUpdate' => true, // 預設開啟
'afterAjaxUpdate' => 'js:function(id, data) { console.log("分頁更新完成"); }',

3. 大資料量深分頁優化

// 避免 OFFSET 1000000 效能崩潰,改用游標分頁
$criteria->condition = 'id > :last_id';
$criteria->params[':last_id'] = $lastSeenId;
$criteria->order = 'id ASC';
$criteria->limit = 20;
// 前端改為「載入更多」按鈕而非頁碼導航

4. 分頁快取策略

// 控制器
$cacheKey = "news_list_page_{$page}_size_{$pageSize}";
if (($data = Yii::app()->cache->get($cacheKey)) === false) {
    $data = $dataProvider->getData();
    Yii::app()->cache->set($cacheKey, $data, 300); // 快取 5 分鐘
}

根據業務場景選擇適合的分頁方式,結合快取、索引優化與前端體驗設計,構建高效能、用戶友好的列表展示系統。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved