所有 Zii 資料展示元件 (CGridView、CListView、CDetailView) 均接受實作 IDataProvider 的物件,提供統一的分頁、排序、資料存取介面。
| 類別 | 資料來源 | 適用場景 | 關鍵屬性 |
|---|---|---|---|
| CActiveDataProvider | ActiveRecord | 標準 ORM 查詢、關聯預載入、動態篩選 | modelClass, criteria, pagination, sort |
| CArrayDataProvider | 原始陣列 / DAO 結果 | 非 AR 資料、靜態陣列、複雜 SQL 結果 | rawData, keyField, pagination, sort |
| CSqlDataProvider | 原生 SQL 查詢 | 報表、存儲過程、跨庫查詢、不需 AR 映射 | sql, totalItemCount, pagination, sort |
$dataProvider = new CActiveDataProvider('Post', [
'criteria' => [
'condition' => 'status=:status',
'params' => [':status' => 1],
'order' => 'create_time DESC',
'with' => ['author', 'categories'], // 預載入關聯
'together' => true, // 強制單次 JOIN 查詢 (HAS_MANY 關聯分頁必須)
],
'pagination' => [
'pageSize' => 20,
'pageVar' => 'page', // URL 參數名
],
'sort' => [
'defaultOrder' => 'create_time DESC',
'attributes' => [
'title',
'create_time',
'authorName' => ['asc' => 'author.username', 'desc' => 'author.username DESC'], // 虛擬屬性排序
],
],
]);
// 取得資料
$posts = $dataProvider->getData(); // 當前頁 AR 實例陣列
$total = $dataProvider->getTotalItemCount(); // 總筆數
$pagination = $dataProvider->getPagination(); // CPagination 物件
$sort = $dataProvider->getSort(); // CSort 物件
// 方式一:DAO 查詢結果
$rawData = Yii::app()->db->createCommand()
->select('id, username, email')
->from('tbl_user')
->queryAll();
$dataProvider = new CArrayDataProvider($rawData, [
'id' => 'user',
'keyField' => 'id', // 唯一鍵欄位
'sort' => [
'attributes' => ['id', 'username', 'email'],
],
'pagination' => ['pageSize' => 10],
]);
// 方式二:AR findAll 結果
$rawData = User::model()->findAll();
$dataProvider = new CArrayDataProvider($rawData, [
'keyField' => 'id',
'sort' => ['attributes' => ['id', 'username', 'email']],
'pagination' => ['pageSize' => 10],
]);
// 必須提供總筆數 (用於分頁計算)
$count = Yii::app()->db->createCommand(
'SELECT COUNT(*) FROM tbl_user WHERE status=1'
)->queryScalar();
$sql = 'SELECT id, username, email, create_time FROM tbl_user WHERE status=1';
$dataProvider = new CSqlDataProvider($sql, [
'totalItemCount' => $count,
'sort' => [
'attributes' => ['id', 'username', 'email', 'create_time'],
],
'pagination' => ['pageSize' => 10],
]);
// 取得資料 (關聯陣列,非 AR 實例)
$users = $dataProvider->getData();
pageSize:每頁筆數。pageVar:URL 頁碼參數名 (預設 page)。route:分頁連結指向路由 (預設當前 Controller/Action)。params:分頁連結額外參數。getCurrentPage()、getPageCount()、getOffset()、getLimit()。attributes:可排序屬性定義,支援虛擬屬性映射真實欄位。defaultOrder:預設排序。sortVar:URL 排序參數名 (預設 sort)。route、params 同 CPagination。getOrderBy():回傳 SQL ORDER BY 子句。resolveLabel():取得屬性顯示標籤。
$this->widget('zii.widgets.grid.CGridView', [
'dataProvider' => $dataProvider,
'ajaxUpdate' => true,
'filter' => $model, // 可選:篩選表單模型
'columns' => [
'id',
'title',
['name' => 'author.username', 'header' => '作者'],
'create_time:datetime',
[
'class' => 'CButtonColumn',
'template' => '{view} {update} {delete}',
],
],
]);
class MyApiDataProvider extends CDataProvider {
private $_apiClient;
public function __construct($apiClient, $config = []) {
$this->_apiClient = $apiClient;
parent::__construct($config);
}
protected function fetchData() {
$pagination = $this->getPagination();
$sort = $this->getSort();
$response = $this->_apiClient->get('/items', [
'limit' => $pagination->getLimit(),
'offset' => $pagination->getOffset(),
'sort' => $sort->getOrderBy(),
]);
return $response['items']; // 陣列
}
protected function calculateTotalItemCount() {
return $this->_apiClient->get('/items/count')['total'];
}
protected function fetchKeys() {
// 回傳當前頁資料的主鍵陣列
return array_column($this->getData(), 'id');
}
}
'together'=>true,否則分頁計數錯誤。'schemaCachingDuration'=>3600 避免每請求讀取元數據。criteria->select 或 CSqlDataProvider 指定欄位,減少傳輸與記憶體。CDataProvider API 文檔 - 完整屬性、方法、事件說明。
