Yii 提供三種主要分頁實作方式,適用於不同複雜度的場景。本文將透過「控制器 + 視圖」的完整程式碼對比,幫助你根據專案需求選擇最適合的方案。
public function actionIndex() {
$criteria = new CDbCriteria();
$count = Article::model()->count($criteria);
$pages = new CPagination($count);
$pages->pageSize = 10;
$pages->applyLimit($criteria); // 關鍵:將 LIMIT/OFFSET 套用到 criteria
$models = Article::model()->findAll($criteria);
$this->render('index', array(
'models' => $models,
'pages' => $pages,
));
}
title); ?>
summary; ?>
widget('CLinkPager', array(
'pages' => $pages,
'header' => '',
'prevPageLabel' => '« 上一頁',
'nextPageLabel' => '下一頁 »',
)); ?>
public function actionIndex() {
$dataProvider = new CActiveDataProvider('News', array(
'criteria' => array(
'condition' => 'status=1',
'order' => 'create_time DESC',
'with' => array('author'), // 急載入關聯
),
'pagination' => array(
'pageSize' => 20,
),
));
$this->render('index', array('dataProvider' => $dataProvider));
}
widget('zii.widgets.CListView', array(
'dataProvider' => $dataProvider,
'itemView' => '_view', // 部分視圖渲染單筆資料
'template' => '{items}{pager}',
'pager' => array(
'class' => 'CLinkPager',
'header' => '',
),
)); ?>
title), array('view', 'id' => $data->id)); ?>
作者:author->name; ?> | create_time); ?>content), 0, 200, 'UTF-8'); ?>...
public function search() {
$criteria = new CDbCriteria;
$criteria->compare('id', $this->id);
$criteria->compare('title', $this->title, true); // 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_date', $this->create_date, true);
return new CActiveDataProvider($this, array(
'criteria' => $criteria,
'pagination' => array('pageSize' => 50),
'sort' => array('defaultOrder' => 'create_date DESC'),
));
}
widget('zii.widgets.grid.CGridView', array(
'id' => 'news-grid',
'dataProvider' => $model->search(),
'filter' => $model, // 欄位搜尋輸入框
'template' => '{items}{summary}{pager}',
'pager' => array(
'class' => 'CLinkPager',
'header' => '分頁:',
'prevPageLabel' => '上一頁',
'nextPageLabel' => '下一頁',
),
'summaryText' => '頁數:{pages}/{page}頁',
'columns' => array(
'id',
array(
'name' => 'title',
'htmlOptions' => array('width' => '20%'),
'value' => 'mb_substr($data->title, 0, 10, "UTF-8")',
),
array(
'name' => 'content',
'htmlOptions' => array('width' => '20%'),
'value' => 'mb_substr(strip_tags($data->content), 0, 10, "UTF-8")',
),
array(
'name' => 'type',
'value' => 'News::model()->getNewsType($data->type)',
),
'user',
array(
'name' => 'status',
'value' => 'News::model()->getNewsStatus($data->status)',
),
array(
'class' => 'CButtonColumn',
'template' => '{view}{update}{delete}',
),
),
)); ?>
| 維度 | CPagination 手動 | CActiveDataProvider + CListView | CGridView + search() |
|---|---|---|---|
| 適用場景 | 簡單列表、特殊查詢邏輯 | 前台文章/商品列表 | 後台管理、複雜搜尋 |
| 程式碼量 | 最多 | 中等 | 最少(聲明式) |
| 搜尋/排序 | 自行實作 | 需額外處理 | 內建支援 |
| 批次操作 | 自行實作 | 需擴充 | CCheckBoxColumn 內建 |
| 效能微調 | 最高彈性 | 良好 | 受限於元件預設 |
複製 framework/web/widgets/pagers/CLinkPager.php 至 protected/components/ZPager.php,修改類名與 CSS 路徑,即可實現完全客製化的分頁 UI。
根據專案階段與需求複雜度選擇分頁模式:原型期用模式一、前台上線用模式二、後台管理用模式三,能讓開發效率與維護性達到最佳平衡。