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

Yii Framework 教程 (28):Data Provider 詳解 - CActiveDataProvider、CArrayDataProvider、CSqlDataProvider

     編輯:PHP 綜合知識

IDataProvider 介面統一資料源

所有 Zii 資料展示元件 (CGridView、CListView、CDetailView) 均接受實作 IDataProvider 的物件,提供統一的分頁、排序、資料存取介面。

三大內建實作對比

類別資料來源適用場景關鍵屬性
CActiveDataProviderActiveRecord標準 ORM 查詢、關聯預載入、動態篩選modelClass, criteria, pagination, sort
CArrayDataProvider原始陣列 / DAO 結果非 AR 資料、靜態陣列、複雜 SQL 結果rawData, keyField, pagination, sort
CSqlDataProvider原生 SQL 查詢報表、存儲過程、跨庫查詢、不需 AR 映射sql, totalItemCount, pagination, sort

CActiveDataProvider 完整配置範例


$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 物件

CArrayDataProvider 範例 (DAO 結果包裝)


// 方式一: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],
]);

CSqlDataProvider 範例 (原生 SQL)


// 必須提供總筆數 (用於分頁計算)
$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();

分頁與排序核心類別

CPagination

  • pageSize:每頁筆數。
  • pageVar:URL 頁碼參數名 (預設 page)。
  • route:分頁連結指向路由 (預設當前 Controller/Action)。
  • params:分頁連結額外參數。
  • getCurrentPage()、getPageCount()、getOffset()、getLimit()。

CSort

  • attributes:可排序屬性定義,支援虛擬屬性映射真實欄位。
  • defaultOrder:預設排序。
  • sortVar:URL 排序參數名 (預設 sort)。
  • route、params 同 CPagination。
  • getOrderBy():回傳 SQL ORDER BY 子句。
  • resolveLabel():取得屬性顯示標籤。

在 View 中使用 (以 CGridView 為例)


$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}',
        ],
    ],
]);

自定義 Data Provider (繼承 CDataProvider)


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');
    }
}

效能優化建議

  1. CActiveDataProvider 關聯分頁:HAS_MANY 關聯分頁必須設定 'together'=>true,否則分頁計數錯誤。
  2. Schema 快取:生產環境 'schemaCachingDuration'=>3600 避免每請求讀取元數據。
  3. 只選必要欄位:criteria->select 或 CSqlDataProvider 指定欄位,減少傳輸與記憶體。
  4. 大資料集避免 CArrayDataProvider:將整個結果集載入記憶體,改用 CSqlDataProvider 或自定義 Provider 流式處理。
  5. 分頁快取:對低變動資料 (如分類列表) 快取 DataProvider 實例或渲染片段。

官方文檔參考

CDataProvider API 文檔 - 完整屬性、方法、事件說明。

Data Provider 類別繼承圖

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