Yii 1.1: Using Zii Components

Exclusive offer: get 50% off this eBook here
Yii 1.1 Application Development Cookbook

Yii 1.1 Application Development Cookbook — Save 50%

Over 80 recipes to help you master using the Yii PHP framework

$26.99    $13.50
by Alexander Makarov | September 2011 | Open Source PHP Web Development

Yii is a very flexible and high-performance application development framework written in PHP. It helps building web applications from small ones to large-scale enterprise applications. The framework name stands for Yes It Is.

In this article by Alexander Makarov, author of Yii 1.1 Application Development Cookbook, we will cover:

  • Using data providers
  • Using grids
  • Using lists
  • Creating custom grid columns

 

(For more resources on this subject, see here.)

Introduction

Yii have a useful library called Zii. It's bundled with framework and includes some classes aimed to make the developer's life easier. Its most handy components are grids and lists which allow you to build data in both the admin and user parts of a website in a very fast and efficient way. In this article you'll learn how to use and adjust these components to fit your needs. Also you'll learn about data providers. They are part of the core framework, not Zii, but since they are used extensively with grids and lists, we'll review them here.

We'll use Sakila sample database version 0.8 available from official MySQL website: http://dev.mysql.com/doc/sakila/en/sakila.html.

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 there are CActiveDataProvider, CArrayDataProvider, and CSqlDataProvider implemented to get data from ActiveRecord models, arrays, and SQL queries respectively.

Let's try all these providers to fill a grid with data.

Getting ready

  • Create a new application using yiic webapp as described in the official guide.
  • Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html and execute the downloaded SQLs: first schema then data.
  • Configure the DB connection in protected/config/main.php.
  • 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 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'=>false),
    )
    ));

    $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'=>'Y!!',
    'id'=>'1644',
    'forumName'=>'Y!!',
    'memberSince'=>'Aug 2010',
    'location'=>'Germany',
    'duty'=>'core framework development',
    'active'=>true,
    ),
    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' => true, 'name' => false),
    ),
    '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' => false),
    ),
    'pagination'=>array(
    'pageSize'=>10,
    ),
    ));

    $this->render('index', array(
    'dataProvider' => $dataProvider,
    ));
    }
    }

  3. Now run grid/aR, grid/array and grid/sql actions and try using the grids.

    Yii 1.1: Using Zii Components

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 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 active record models. Model class is passed as a first argument of class constructor. Second argument is an array that defines class public properties. In the code above, we are setting pagination to 10 items per page and default sorting by title.

Note that instead of using a string we are using an array where keys are column names and values are true or false. true means order is DESC while false means that order is ASC. Defining the default order this way allows Yii to render a triangle showing 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,
),
));

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

In actionSQL, we are using CSqlDataProvider that consumes the SQL query and modifies it automatically allowing pagination. First argument accepts a string with SQL and a second argument with data provider parameters. This time we need to supply calculateTotalItemCount with 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 are accepting the following properties:

pagination

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

sort

CSort object or an array of initial values for 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 protected/views/grid/ index.php content with the following:

<?php foreach($dataProvider->data as $film):?>
<?php echo $film->title?>
<?php endforeach?>

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

Further reading

To learn more about data providers refer to the following API pages:

 

Using grids

Zii grids are very useful to quickly create efficient application admin pages or any pages you need to manage data on.

Let's use Gii to generate a grid, see how it works, and how we can customize it.

Getting ready

Carry out the following steps:

  • Create a new application using yiic webapp as described in the official guide.
  • Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html. Execute the downloaded SQLs: first schema then data.
  • Configure the DB connection in protected/config/main.php.
  • Use Gii to create models for customer, address, and city tables.

How to do it...

  1. Open Gii, select Crud Generator, and enter Customer into the Model Class field. Press Preview and then Generate.
  2. Gii will generate a controller in protected/controllers/CustomerController.php and a group of views under protected/views/customer/.
  3. Run customer controller and go to Manage Customer link. After logging in you should see the grid generated:

    Yii 1.1: Using Zii Components

How it works...

Let's start with the admin action of customer controller:

public function actionAdmin()
{
$model=new Customer('search');
$model->unsetAttributes(); // clear any default values
if(isset($_GET['Customer']))
$model->attributes=$_GET['Customer'];

$this->render('admin',array(
'model'=>$model,
));
}

Customer model is created with search scenario, all attribute values are cleaned up, and then filled up with data from $_GET. On the first request $_GET is empty but when you are changing the page, or filtering by first name attribute using the input field below the column name, the following GET parameters are passed to the same action via an AJAX request:

Customer[address_id] =
Customer[customer_id] =
Customer[email] =

Customer[first_name] = alex
Customer[last_name] =
Customer[store_id] =
Customer_page = 2
ajax = customer-grid

Since scenario is search, the corresponding validation rules from Customer::rules are applied. For the search scenario, Gii generates a safe rule that allows to mass assigning for all fields:

array('customer_id, store_id, first_name, last_name, email,
address_id, active, create_date, last_update', 'safe',
'on'=>'search'),

Then model is passed to a view protected/views/customer/admin.php. It renders advanced search form and then passes the model to the grid widget:

<?php $this->widget('zii.widgets.grid.CGridView', array(
'id'=>'customer-grid',
'dataProvider'=>$model->search(),
'filter'=>$model,
'columns'=>array(
'customer_id',
'store_id',
'first_name',
'last_name',
'email',
'address_id',
/*
'active',
'create_date',
'last_update',
*/
array(
'class'=>'CButtonColumn',
),
),
)); ?>

Columns used in the grid are passed to columns. When just a name is passed, the corresponding field from data provider is used.

Also we can use custom column represented by a class specified. In this case we are using CButtonColumn that renders view, update and delete buttons that are linked to the same named actions and are passing row ID to them so action can be done to a model representing specific row from database.

filter property accepts a model filled with data. If it's set, a grid will display multiple text fields at the top that the user can fill to filter the grid.

The dataProvider property takes an instance of data provider. In our case it's returned by the model's search method :

public function search()
{
// Warning: Please modify the following code to remove attributes
that
// should not be searched.

$criteria=new CDbCriteria;

$criteria->compare('customer_id',$this->customer_id);
$criteria->compare('store_id',$this->store_id);
$criteria->compare('first_name',$this->first_name,true);
$criteria->compare('last_name',$this->last_name,true);
$criteria->compare('email',$this->email,true);
$criteria->compare('address_id',$this->address_id);
$criteria->compare('active',$this->active);
$criteria->compare('create_date',$this->create_date,true);
$criteria->compare('last_update',$this->last_update,true);

return new CActiveDataProvider(get_class($this), array(
'criteria'=>$criteria,
));
}

This method is called after the model was filled with $_GET data from the filtering fields so we can use field values to form the criteria for the data provider. In this case all numeric values are compared exactly while string values are compared using partial match.

Yii 1.1 Application Development Cookbook Over 80 recipes to help you master using the Yii PHP framework
Published: August 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

 

(For more resources on this subject, see here.)

There's more...

Code generated by Gii can be useful in a lot of simple cases but often we need to customize it.

Using data from related Active Record models

In the code, the generated grid displays the store and address IDs instead of corresponding values. Let's fix the address and display city, district, and address instead of just ID.

  1. We have the following relations in the Customer model:

    public function relations()
    {
    // NOTE: you may need to adjust the relation name and
    the related
    // class name for the relations automatically generated below.
    return array(
    'address' => array(self::BELONGS_TO, 'Address', 'address_id'),
    'store' => array(self::BELONGS_TO, 'Store', 'store_id'),
    'payments' => array(self::HAS_MANY, 'Payment', 'customer_id'),
    'rentals' => array(self::HAS_MANY, 'Rental', 'customer_id'),
    );
    }

  2. We need to load address data along with the model. That means we have to add these to the with part of the criteria passed to the data provider in Customer::search. Since the address includes city ID, we need to load the city data using the city relation of the Address model.

    public function search()
    {
    // Warning: Please modify the following code to remove
    //attributes that should not be searched.

    $criteria=new CDbCriteria;

    $criteria->with = array('address' => array(
    'with' => 'city'
    )); ...

    Each relation used in the with part of the criteria can be specified in the way shown above where key is the relation name and value is an array representing criteria. These criteria will be applied to the related model.

  3. Now let's modify the columns list passed to a grid in protected/views/customer/admin.php:

    'columns'=>array(
    'customer_id',
    'store_id',
    'first_name',
    'last_name',
    'email',
    array(
    'name'=>'address',
    'value'=>'$data->address->address.",
    ".$data->address->city->city.",
    ".$data->address->district',
    ),

  4. In the preceding code, we are using a relation name of name and setting value to a string consisting of address, city, and district.
    Now check the grid. It should now list address, city, and district in the address field.

    Yii 1.1: Using Zii Components

  5. The only problems now are that address is not sortable and filtering using address does not work.
    Let's fix the sorting first. In the Customer::search method we need to create CSort instance, configure it, and pass it to the data provider:

    $sort = new CSort;
    $sort->attributes = array(
    'address' => array(
    'asc' => 'address, city, district',
    'desc' => 'address DESC, city DESC, district DESC',
    ),
    '*',
    );
    return new CActiveDataProvider(get_class($this), array(
    'criteria'=>$criteria,
    'sort'=>$sort,
    ));

    CSort::attributes accepts a list of sortable attributes. We want all Customer attributes to be sortable so we are adding * to the list. Additionally we are specifying SQL for both ascending and descending sorting of the address attribute.
    That's it. Sorting should work.

  6. Now let's fix filtering. First we need to add address to the safe attributes list in the model's rules method. Then we are replacing comparison in Customer::search:

    $criteria->compare('address_id',$this->address_id);

    should be replaced with:

    $criteria->compare('address',$this->address,true);
    $criteria->compare('district',$this->address,true,"OR");
    $criteria->compare('city',$this->address,true,"OR");

  7. When a user enters california in the address filter field, the three compares above will result in SQL like the following:

    WHERE address LIKE '%california%'
    OR district LIKE '%california%'
    OR city LIKE '%california%'

    Yii 1.1: Using Zii Components

Further reading

To learn more about grids and its properties refer to the following resources:

Using lists

Zii lists are a good tool to display data from any data provider to end users while handling pagination and sorting automatically. CListView is very customizable so it allows building any type of list page.

Let's use Gii to generate a list, see how it works, and how we can customize it.

Getting ready

  • Create a new application using yiic webapp as described in the official guide.
  • Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html. Execute the downloaded SQLs: first schema then data.
  • Configure the DB connection in protected/config/main.php.
  • Use Gii to create models for customer, store, address, and city tables.

How to do it...

  1. Open Gii, select Crud Generator, and enter Customer into the Model Class field. Press Preview and then Generate.
  2. Gii will generate a controller in protected/controllers/CustomerController.php and a group of views under protected/views/ customer/.
  3. Run, index action of customer controller to see the customers list in action.

    Yii 1.1: Using Zii Components

How it works...

Let's start with the index action of Customer controller:

public function actionIndex()
{
$dataProvider=new CActiveDataProvider('Customer');
$this->render('index',array(
'dataProvider'=>$dataProvider,
));
}

It's very simple: new active data provider for the Customer model is created and passed into the protected/views/customer/index.php view where it is used in the CListView widget:

<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
)); ?>

itemView specifies a view partially used to render each data row. In our case it's protected/views/customer/_view.php that lists all attribute names and values like the following:

<b><?php echo CHtml::encode($data->getAttributeLabel(
'first_name')); ?>:</b>
<?php echo CHtml::encode($data->first_name); ?>

$data in the code above refers to a model representing a data row that came from the data provider.

There's more...

If you are using lists in real applications, most likely you'll want to customize them.

Adding sorting

Let's add ability to sort by last name and email. To implement it we need to define sortableAttributes property :

<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
'sortableAttributes'=>array(
'last_name',
'email',
),
)); ?>

Customizing templates

Let's add pagination and sorter at the top and the bottom, and remove the summary. To implement all these we need to customize just one widget property called template:

<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
'sortableAttributes'=>array(
'last_name',
'email',
),
'template' => '{sorter} {pager} {items} {sorter} {pager}',
)); ?>

 

Yii 1.1: Using Zii Components

Customizing markup and data displayed

Let's tweak list markup and templates starting with the widget parameters:

<?php $this->widget('zii.widgets.CListView', array(
'dataProvider'=>$dataProvider,
'itemView'=>'_view',
'itemsTagName' => 'ol',
'itemsCssClass' => 'customers',
'sortableAttributes'=>array(
'last_name',
'email',
),
'template' => '{sorter} {pager} {items} {sorter} {pager}',
)); ?>

itemsTagName defines a tag that will be used as a base tag for a list. In this case the list is ordered so we are using ol. itemsCssClass sets a class for this ol.

We need to modify protected/views/customer/_view.php:

<li>
<h2>
<?php
$title = CHtml::encode($data->first_name.' '.$data->last_name);
echo CHtml::link($title, array('view', 'id'=>
$data->customer_id));
?>
</h2>

<ul>
<li>
<strong><?php echo CHtml::encode($data->
getAttributeLabel('store_id')); ?>:</strong>
<?php echo CHtml::encode($data->store->
address->address.', '.$data->store->address->city->city.',
'.$data->store->address->district); ?>
</li>
<li>
<strong><?php echo CHtml::encode($data->
getAttributeLabel('email')); ?>:</strong>
<?php echo CHtml::encode($data->email); ?>
</li>
<li>
<strong><?php echo CHtml::encode($data->
getAttributeLabel('address_id')); ?>:</strong>
<?php echo CHtml::encode($data->address->address.',
'.$data->address->city->city.',
'.$data->address->district); ?>
</li>
<li>
<strong><?php echo CHtml::encode($data->
getAttributeLabel('active')); ?>:</strong>
<?php echo $data->active ? 'Yes' : 'No'; ?>
</li>
</ul>
</li>

Let's apply some CSS. Create protected/assets/customers.css:

ol.customers {
list-style: none;
margin: 1em 0;
}

ol.customers>li {
margin: 1em;
padding:1em;
background: #fcfcfc;
border: 1px solid #9aafe5;
}

Then you need to add the following to protected/views/customer/_view.php:

<?php Yii::app()->clientScript->registerCssFile(
Yii::app()->assetManager->publish(Yii::getPathOfAlias('application.
assets').
'/customers.css'))?>

After applying styles, the list will look like this:

Yii 1.1: Using Zii Components

Further reading

To learn more about lists refer to the following API page:

Creating custom grid columns

Most of the time you don't need to create your own grid column types since the ones included in Yii are pretty flexible and are suitable for most use cases. Still, there are situations when you need to create a custom column.

Let's create a custom grid column that will allow a toggling Y/N value that will change the corresponding model value via AJAX.

Getting ready

  • Create a new application using yiic webapp as described in the official guide.
  • Download the Sakila database from http://dev.mysql.com/doc/sakila/en/sakila.html. Execute the downloaded SQLs: first schema then data.
  • Configure the DB connection in protected/config/main.php.
  • Use Gii to create model for the customer table.
  • Open Gii, select "Crud Generator " and enter Customer into the "Model Class" field. Press "Preview" and then "Generate".
  • Gii will generate the controller in protected/controllers/CustomerController.php and a group of views under protected/views/customer/.
  • Run customer controller and go to the "Manage Customer" link. After logging in you should see the grid generated.

How to do it...

In the table we have an active field that we want to toggle with the flag column. Column should display Y or N depending on what the value is and should allow toggling of the value by clicking on it. Grid should stay on the same page.

  1. Let's create protected/components/FlagColumn.php:

    <?php
    class FlagColumn extends CGridColumn
    {
    public $name;
    public $sortable=true;
    public $callbackUrl = array('flag');
    private $_flagClass = "flag_link";

    public function init() {
    parent::init();
    $cs=Yii::app()->getClientScript();
    $gridId = $this->grid->getId();
    $script = <<<SCRIPT
    jQuery(".{$this->_flagClass}").live("click", function(e){
    e.preventDefault();
    var link = this;
    $.ajax({
    dataType: "json",
    cache: false,
    url: link.href,
    success: function(data){
    $('#$gridId').yiiGridView.update('$gridId');
    }
    });
    });
    SCRIPT;
    $cs->registerScript(__CLASS__.$gridId.'#flag_link', $script);
    }

    protected function renderDataCellContent($row, $data) {
    $value=CHtml::value($data,$this->name);

    $this->callbackUrl['pk'] = $data->primaryKey;
    $this->callbackUrl['name'] = urlencode($this->name);
    $this->callbackUrl['value'] = (int)empty($value);

    $link = CHtml::normalizeUrl($this->callbackUrl);

    echo CHtml::link(!empty($value) ? 'Y' : 'N', $link, array(
    'class' => $this->_flagClass,
    ));
    }

    protected function renderHeaderCellContent()
    {
    if($this->grid->enableSorting && $this->sortable &&
    $this->name!==null)
    echo $this->grid->dataProvider->getSort()->link(
    $this->name,$this->header);
    else if($this->name!==null && $this->header===null)
    {
    if($this->grid->dataProvider instanceof CActiveDataProvider)
    echo CHtml::encode($this->grid->dataProvider->
    model->getAttributeLabel($this->name));
    else
    echo CHtml::encode($this->name);
    }
    else
    parent::renderHeaderCellContent();
    }
    }

  2. Now in protected/controllers/CustomerController.php we need to implement actionFlag:

    public function actionFlag($pk, $name, $value){
    $model = $this->loadModel($pk);
    $model->{$name} = $value;
    $model->save(false);

    if(!Yii::app()->request->isAjaxRequest){
    $this->redirect('admin');
    }
    }

  3. Finally we need to use it in a grid, protected/views/customer/admin.php:

    ...
    <?php $this->widget('zii.widgets.grid.CGridView', array(
    'id'=>'customer-grid',
    'dataProvider'=>$model->search(),
    'filter'=>$model,
    'columns'=>array(
    'customer_id',
    'store_id',
    'first_name',
    'last_name',
    'email',
    'address_id',
    array(
    'class' => 'FlagColumn',
    'name' => 'active',
    ),
    /*
    'create_date',
    'last_update',
    */
    array(
    'class'=>'CButtonColumn',
    ),
    ),
    )); ?>
    ...

  4. Now check the grid. It should contain an Active column with Y and N as values:

    Yii 1.1: Using Zii Components

How it works...

When calling a grid widget we can pass an array specifying column class and setting public properties of this class.


'columns'=>array(
'customer_id',
'store_id',
'first_name',
'last_name',
'email',
'address_id',
array(
'class' => 'FlagColumn',
'name' => 'active',
),

In the code above we are using FlagColumn class and setting its name property to active.

class FlagColumn extends CGridColumn

A grid column should extend CGridColumn and implement at least the renderDataCellContent method:

protected function renderDataCellContent($row, $data) {
$value=CHtml::value($data,$this->name);
$this->callbackUrl['pk'] = $data->primaryKey;
$this->callbackUrl['name'] = urlencode($this->name);
$this->callbackUrl['value'] = (int)empty($value);

$link = CHtml::normalizeUrl($this->callbackUrl);

echo CHtml::link(!empty($value) ? 'Y' : 'N', $link, array(
'class' => $this->_flagClass,
));
}

Everything echoed in this method will be displayed as the cell content. $row is a row number, $data is a model instance representing a row. Using CHtml::value we are getting the value of active field and passing its name and value along with the model primary key to CHtml::normalizeUrl to create a link to the flag action.

Now we need to add some AJAX. We are doing it in the init method:

public function init() {
parent::init();
$cs=Yii::app()->getClientScript();
$gridId = $this->grid->getId();
$script = <<<SCRIPT
jQuery(".{$this->_flagClass}").live("click", function(e){
e.preventDefault();
var link = this;
$.ajax({
dataType: "json",
cache: false,
url: link.href,
success: function(data){
$('#$gridId').yiiGridView.update('$gridId');
}
});
});
SCRIPT;
$cs->registerScript(__CLASS__.$gridId.'#flag_link', $script);
}

For each link we've created in the renderDataCellContent method , we are adding a click event handler. live usage is needed to handle the grid's AJAX pagination properly. On clicking we are making an AJAX request to flag action. On success we are refreshing the grid.

Action itself is very straightforward. We are getting the model instance, setting a field, and saving the model.

To support sorting, FlagColumn implements another method:

protected function renderHeaderCellContent()
{
if($this->grid->enableSorting && $this->sortable &&
$this->name!==null)
echo $this->grid->dataProvider->getSort()->link(
$this->name,$this->header);
else if($this->name!==null && $this->header===null)
{
if($this->grid->dataProvider instanceof CActiveDataProvider)
echo CHtml::encode($this->grid->dataProvider->
model->getAttributeLabel($this->name));
else
echo CHtml::encode($this->name);
}
else
parent::renderHeaderCellContent();
}

This is the exact copy of the method named CDataProvider. If both grid and column sorting are enabled, we are displaying a link to sort a grid.

There's more...

For further Information refer to:

Summary

This article covered data providers, grids, and lists: How to configure sorting and search, how to use grids with multiple related models, how to create your own column types, and more.


Further resources related to this subject:


Yii 1.1 Application Development Cookbook Over 80 recipes to help you master using the Yii PHP framework
Published: August 2011
eBook Price: $26.99
Book Price: $44.99
See more
Select your format and quantity:

About the Author :


Alexander Makarov

Alexander Makarav is an experienced engineer from Russia and has been a Yii framework core team member since 2010. Before joining the Yii core team, he participated in the CodeIgniter community growth in Russia. In 2009, he finished the Russian translation of the framework documentation and created the Russian community website. In 2012, he released the Russian version of the book along with Russian community members. In the same year, he was the technical reviewer for three more books:

  • The Yii Book: Developing Web Applications Using the Yii PHP Framework, Larry Ullman
  • Web Application Development with Yii and PHP, Jeff Winesett
  • Yii Rapid Application Development Hotshot, Lauren O'Meara and James Hamilton

In his free time, Alexander writes technical blog at http://rmcreative.ru/, speaks at conferences, and enjoys movies, music, traveling, photography, and languages. He currently resides in Voronezh, Russia with his beloved wife and daughter.

Books From Packt


Agile Web Application Development with Yii1.1 and PHP5
Agile Web Application Development with Yii1.1 and PHP5

Yahoo! User Interface Library 2.x Cookbook
Yahoo! User Interface Library 2.x Cookbook

YUI 2.8: Learning the Library
YUI 2.8: Learning the Library

PHP 5 CMS Framework Development - 2nd Edition
PHP 5 CMS Framework Development - 2nd Edition

Expert PHP 5 Tools
Expert PHP 5 Tools

PHP jQuery Cookbook
PHP jQuery Cookbook

CakePHP 1.3 Application Development Cookbook
CakePHP 1.3 Application Development Cookbook

Drupal 7 First Look
Drupal 7 First Look


Code Download and Errata
Packt Anytime, Anywhere
Register Books
Print Upgrades
eBook Downloads
Video Support
Contact Us
Awards Voting Nominations Previous Winners
Judges Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software
Resources
Open Source CMS Hall Of Fame CMS Most Promising Open Source Project Open Source E-Commerce Applications Open Source JavaScript Library Open Source Graphics Software