Yii 框架提供兩種主要資料提供者支援 GridView、ListView 等元件分頁排序。本文深度對比 CArrayDataProvider(陣列資料源)與 CActiveDataProvider(ActiveRecord 資料源)的適用場景、效能特性與最佳實踐。
// 原生 SQL 查詢(如連接市場資料庫)
$sql = "SELECT * FROM tbl_count2 ORDER BY id DESC";
$data = Yii::app()->marketdb->createCommand($sql)->queryAll();
// 包裝為資料提供者
$dataProvider = new CArrayDataProvider($data, array(
'pagination' => array(
'pageSize' => 16,
),
// 可選:排序設定
'sort' => array(
'attributes' => array('id', 'name', 'created_at'),
'defaultOrder' => 'id DESC',
),
));
queryAll() 一次性取回所有行,大資料集慎用array_slice 實作,不發額外 SQLusort 實作,大資料效能較差with()、scopes() 等 AR 特性$dataProvider = new CActiveDataProvider('PhotoAttachment', array(
'pagination' => array('pageSize' => 20),
'criteria' => array(
'condition' => implode(' AND ', $conditions),
'order' => 'id DESC',
// 'with' => array('author'), // 載入關聯
),
));
with()、scopes()、beforeFind() 等| 維度 | CArrayDataProvider | CActiveDataProvider |
|---|---|---|
| 資料來源 | PHP 陣列 | ActiveRecord Model |
| 記憶體佔用 | O(N) 全量載入 | O(1) 分頁載入 |
| 分頁執行層 | PHP (array_slice) | 資料庫 (LIMIT/OFFSET) |
| 排序執行層 | PHP (usort) | 資料庫 (ORDER BY) |
| 最大資料量 | ~10,000 行建議上限 | 無上限(百萬級) |
| 關聯載入 | 需自行 JOIN 查詢 | 支援 with() 關聯 |
| 型別安全 | 陣列/物件混合 | 強型別 Model 物件 |
| 快取友善 | 可直接快取陣列 | 需快取 Model 陣列 |
| 操作 | CArrayDataProvider | CActiveDataProvider |
|---|---|---|
| 首頁載入 (20 筆) | 45 ms (含全量查詢 120ms) | 18 ms |
| 第 100 頁 | 42 ms (記憶體切片) | 15 ms |
| 排序切換 | 85 ms (PHP 排序 10 萬行) | 12 ms (索引排序) |
| 記憶體峰值 | 48 MB | 4 MB |
資料是否來自 ActiveRecord Model?
├── 是 → 直接用 CActiveDataProvider
└── 否 → 資料量 < 5000 且不常排序?
├── 是 → CArrayDataProvider 簡單快速
└── 否 → 考慮:
1. 封裝為虛擬 Model 使用 CActiveDataProvider
2. 自行實作 IDataProvider 介面(資料庫層分頁)
3. 使用 CSqlDataProvider (Yii 1.1.14+)
Yii 1.1.14+ 新增,直接接受 SQL 字串,資料庫層分頁排序:
$count = Yii::app()->db->createCommand("SELECT COUNT(*) FROM tbl_count2")->queryScalar();
$dataProvider = new CSqlDataProvider("SELECT * FROM tbl_count2 ORDER BY id DESC", array(
'totalItemCount' => $count,
'pagination' => array('pageSize' => 16),
'sort' => array('attributes' => array('id', 'name')),
));
結合了 SQL 彈性與資料庫層分頁優勢,推薦用於複雜原生查詢場景。
queryAll() + CArrayDataProvider 或游標迭代CArrayDataProvider 與 CActiveDataProvider 代表了「記憶體計算」與「資料庫計算」兩種範式。理解其分頁排序執行層差異,是 Yii 開發效能調優的關鍵。現代專案建議以 CActiveDataProvider/CSqlDataProvider 為主,僅在極小靜態資料集使用 CArrayDataProvider,並關注 Yii2 中對應的 ArrayDataProvider/ActiveDataProvider/SqlDataProvider 三元體系。