Using data providers

Data providers are used to encapsulate common data model operations such as sorting, pagination, and querying. They are used with grids and lists extensively. Because both widgets and providers are standardized, you can display the same data using different widgets and you can get data for a widget from various providers. Switching providers and widgets is relatively transparent.

Currently CActiveDataProvider, CArrayDataProvider, and CSqlDataProvider are implemented to get data from Active Record models, arrays, and SQL queries respectively. Let's try all these providers to fill a grid with data.

Getting ready

  1. Create a new application using yiic webapp as described in the official guide.
  2. Download the Sakila database from http://dev.mysql.com/doc/index-other.html and execute the downloaded SQLs (first schema then data).
  3. Configure the database connection in protected/config/main.php.
  4. Use Gii to create a model for the film table.

How to do it...

  1. Let's start with a view for a grid controller. Create protected/views/grid/index.php:
    <?php $this->widget('zii.widgets.grid.CGridView', array('dataProvider' => $dataProvider,
    ))?>
  2. Then create a controller, protected/controllers/GridController.php:
    <?php
    class GridController extends Controller
    {
      public function actionAR()
      {
        $dataProvider = new CActiveDataProvider('Film', array(
          'pagination'=>array(
            'pageSize'=>10,
          ),
          'sort'=>array(
            'defaultOrder'=> array('title'=> CSort::SORT_ASC),
          )
        ));
    
        $this->render('index', array(
          'dataProvider' => $dataProvider,
        ));
      }
    
      public function actionArray()
      {
        $yiiDevelopers = array(
          array(
            'name'=>'Qiang Xue',
            'id'=>'2',
            'forumName'=>'qiang',
            'memberSince'=>'Jan 2008',
            'location'=>'Washington DC, USA',
            'duty'=>'founder and project lead',
            'active'=>true,
          ),
          array(
            'name'=>'Wei Zhuo',
            'id'=>'3',
            'forumName'=>'wei',
            'memberSince'=>'Jan 2008',
            'location'=>'Sydney, Australia',
            'duty'=>'project site maintenance and development',
            'active'=>true,
          ),
          array(
            'name'=>'Sebastián Thierer',
            'id'=>'54',
            'forumName'=>'sebas',
            'memberSince'=>'Sep 2009',
            'location'=>'Argentina',
            'duty'=>'component development',
            'active'=>true,
          ),
          array(
            'name'=>'Alexander Makarov',
            'id'=>'415',
            'forumName'=>'samdark',
            'memberSince'=>'Mar 2010',
            'location'=>'Russia',
            'duty'=>'core framework development',
            'active'=>true,
          ),
          array(
            'name'=>'Maurizio Domba',
            'id'=>'2650',
            'forumName'=>'mdomba',
            'memberSince'=>'Aug 2010',
            'location'=>'Croatia',
            'duty'=>'core framework development',
            'active'=>true,
          ),
          array(
            'name'=>'Carsten Brandt',
            'id'=>'5951',
            'forumName'=>'CeBe',
            'memberSince'=>'Aug 2012',
            'location'=>'Berlin, Germany',
            'duty'=>'core framework development',
            'active'=>true,
          ),
          array(
            'name'=>'Y!!',
            'id'=>'1644',
            'forumName'=>'Y!!',
            'memberSince'=>'Aug 2010',
            'location'=>'Germany',
            'duty'=>'core framework development',
            'active'=>false,
          ),
          array(
            'name'=>'Jeffrey Winesett',
            'id'=>'15',
            'forumName'=>'jefftulsa',
            'memberSince'=>'Sep 2010',
            'location'=>'Austin, TX, USA',
            'duty'=>'documentation and marketing',
            'active'=>true,
          ),
          array(
            'name'=>'Jonah Turnquist',
            'id'=>'127',
            'forumName'=>'jonah',
            'memberSince'=>'Sep 2009 - Aug 2010',
            'location'=>'California, US',
            'duty'=>'component development',
            'active'=>false,
          ),
          array(
            'name'=>'István Beregszászi',
            'id'=>'1286',
            'forumName'=>'pestaa',
            'memberSince'=>'Sep 2009 - Mar 2010',
            'location'=>'Hungary',
            'duty'=>'core framework development',
            'active'=>false,
          ),
        );
    
        $dataProvider = new CArrayDataProvider($yiiDevelopers, array(
          'sort'=>array(
            'attributes'=>array('name', 'id', 'active'),
            'defaultOrder'=>array('active' => CSort::SORT_DESC, 'name' => CSort::SORT_ASC),
          ),
          'pagination'=>array(
            'pageSize'=>10,
          ),
        ));
    
        $this->render('index', array(
          'dataProvider' => $dataProvider,
        ));
      }
    
      public function actionSQL()
      {
        $count=Yii::app()->db->createCommand('SELECT COUNT(*) FROM film')->queryScalar();
        $sql='SELECT * FROM film';
        $dataProvider=new CSqlDataProvider($sql, array(
          'keyField'=>'film_id',
          'totalItemCount'=>$count,
          'sort'=>array(
            'attributes'=>array('title'),
            'defaultOrder'=>array('title' => CSort::SORT_ASC),
          ),
          'pagination'=>array(
            'pageSize'=>10,
          ),
        ));
        $this->render('index', array(
          'dataProvider' => $dataProvider,
        ));
      }
    }
  3. Now run the grid/aR, grid/array, and grid/sql actions and try using the grids.
    How to do it...

How it works...

The view is pretty simple and stays the same for all data providers. We are calling the grid widget and passing the data provider instance to it.

Let's review the actions one by one starting with actionAR:

$dataProvider = new CActiveDataProvider('Film', array(
  'pagination'=>array(
    'pageSize'=>10,
  ),
  'sort'=>array(
    'defaultOrder'=>array('title'=>false),
  )
));

CActiveDataProvider works with AR models. The model class is passed as a first argument of the class constructor. The second argument is an array that defines class public properties. In the previous code, we are setting the pagination to 10 items per page and default sorting by title.

Tip

Note that instead of using a string we are using an array where keys are column names and values are CSort::SORT_ASC or CSort::SORT_DESC. Defining the default order this way allows Yii to render a triangle showing the sorting direction in the column header.

In actionArray we are using CArrayDataProvider that can consume any array.

$dataProvider = new CArrayDataProvider($yiiDevelopers, array(
  'sort'=>array(
    'attributes'=>array('name', 'id', 'active'),
    'defaultOrder'=>array('active' => true, 'name' => false),
  ),
  'pagination'=>array(
    'pageSize'=>10,
  ),
));

The first argument accepts an associative array where keys are column names and values are corresponding values. The second argument accepts an array with the same options as in the CActiveDataProvider case.

In actionSQL, we are using CSqlDataProvider that consumes the SQL query and modifies it automatically allowing pagination. The first argument accepts a string with SQL and the second argument with data provider parameters. This time we need to supply calculateTotalItemCount with the total count of records manually. For this purpose we need to execute the extra SQL query manually. Also, we need to define keyField since the primary key of this table is not id but film_id.

To sum up, all data providers accept the following properties:

pagination

The CPagination object or an array of initial values for a new instance of CPagination.

sort

The CSort object or an array of initial values for a new instance of CSort.

totalItemCount

We need to set this only if the provider, such as CSqlDataProvider, does not implement the calculateTotalItemCount method.

There's more...

You can use data providers without any special widgets. Replace the contents of protected/views/grid/index.php with the following:

<?php foreach($dataProvider->data as $film):?>
  <?php echo $film['title'].'<br />'?>
<?php endforeach?>

<?php $this->widget('CLinkPager',array('pages'=>$dataProvider->pagination))?>

See also

  • The Using grids recipe
  • The Using lists recipe
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.145.42.94