web-dev-qa-db-ja.com

Yii CActiveDataProviderオブジェクトを反復処理する方法は?

データプロバイダーオブジェクトを反復処理する方法は?返された各行の「名前」フィールドにアクセスして、リストを作成したいと思います。手伝ってくれますか?

テーブル/モデルのテーブル構造categories

CREATE TABLE IF NOT EXISTS `categories` (
  `idCategory` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `name` varchar(64) NOT NULL,
  PRIMARY KEY (`idCategory`) USING BTREE
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=55 ;

* コントローラーカテゴリの関数*

    $names = array();
    public function returnCategoryNames()
{
    $dataProvider= new CActiveDataProvider('Categories');
    $dataProvider->setPagination(false);
    $count = $dataProvider->totalItemCount();

    for($i = 0; $i < $count; $i++){

             // this is where I am lost...
             $myname = $dataProvider->data[$i]->name;
             array_Push($names, $myname);

    }   

       return $names;

}
12
eric

これを試して:

public function returnCategoryNames()
{
  $dataProvider= new CActiveDataProvider('Categories');
  $dataProvider->setPagination(false);
  //$count = $dataProvider->totalItemCount();
  $names = array();
  foreach($dataProvider->getData() as $record) {
    $names[] = $record->name;
  }
  return array_unique($names);
}

ただし、データプロバイダーを使用する必要はなく、モデルを使用するだけです。

foreach(Categories::model()->findAll() as $record) {
20
Ben Rowe

大規模なデータ収集を行う必要があり、メモリ使用量が心配な場合は、次のようにします。

$dataProvider = new CActiveDataProvider('Categories');
$iterator = new CDataProviderIterator($dataProvider);
foreach($iterator as $category) {
   print_r($category);
}

CDataProviderIteratorを使用すると、セット全体をメモリに保持することなく、大きなデータセットを反復処理できます。

いくつかのパフォーマンステスト

テスト時間(秒)メモリ(バイト)
 CDbDataReader 4.9158580303192 28339952 
 CActiveRecord :: findAll()5.8891110420227 321388376 
 CDataProviderIterator 6.101970911026 31170504 [.____。
14
Akim Kelar

Yii2では、これも変更されました。

    $searchModel = new ModelSearch();
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

    foreach($dataProvider->getModels() as $record) {
        echo $record->id . '<br>';
    }

    exit();

参照: getModels()

5
Coz

@ ben-roweのソリューションを使用すると、すべての行を一度にクエリできます。メモリの問題が発生する可能性があります。

次のソリューションでは、カテゴリを10 x 10からフェッチします(デフォルト CPagination.pageSize 値):

        $dataProvider = new CActiveDataProvider('Categories', array(
            'pagination' => array(
                'validateCurrentPage' => false
            ),
        ));
        $pagination = $dataProvider->pagination;
        while ($categories = $dataProvider->getData(true)){
            foreach ($categories as $category) {
                //...
            }
            $pagination->currentPage++;
        }
4
Jorge Barata