CGridView

Update: Check out our new Yii2 Developer Exchange site at http://yii2x.com. It’s devoted exclusively for Yii2 developers to make it easier to find news, tips, tutorials and extensions related to Yii2.

cloud hosting digital ocean SSD wordpress

CGridView

See CGridView in the Yii Framework documentation.

Using Relations in CGridView with a Sub-Query

My Message table display needs to show field values, filter from and sort on relations for Email and Folder. Here’s how you do it:

yii_cgridview_relations

Create model variables for the field names we which to use:

class Message extends CActiveRecord
{
  public $email;
  public $folder_name;

Add the field names to the safe on search rule:

public function rules()
	{
		return array(
			array('message_id, subject, modified_at', 'required'),
...
			array('id, account_id, folder_id, user_id, sender_id, message_id, subject, body_text, body_html, status, cached, udate, email, folder_name, created_at, modified_at', 'safe', 'on'=>'search'), // 
		);
	}

In the Search function, create subqueries for email and folder_name:

public function search()
	{
		$criteria=new CDbCriteria;
		$sender_table = Sender::model()->tableName();
    $email_sql = "(select CONCAT(personal,' <',email,'>') from $sender_table st where st.id = t.sender_id)";
		$folder_table = Folder::model()->tableName();
    $folder_name_sql = "(select name from $folder_table ft where ft.id = t.folder_id)";
    $criteria->select = array(
            '*',
            $email_sql . " as email",
            $folder_name_sql . " as folder_name",
        );    
...
    $criteria->compare($folder_name_sql, $this->folder_name);		  
    $criteria->compare($email_sql, $this->email,true);

In returning the CActiveDataProvider, we include sort capacity for email and folder_name:

return new CActiveDataProvider($this, array(
			'criteria'=>$criteria,
      'pagination' => array(
                  'pageSize' => Yii::app()->params['postsPerPage'],
             ),
      'sort' => array(
        'defaultOrder' => 'created_at desc',
          'attributes' => array(
              // order by
              'created_at' => array(
                  'asc' => 'created_at ASC',
                  'desc' => 'created_at DESC',
              ),
              // order by
              'email' => array(
                  'asc' => 'email ASC',
                  'desc' => 'email DESC',
              ),
              'folder_name' => array(
                  'asc' => 'folder_name ASC',
                  'desc' => 'folder_name DESC',
              ),
              '*',
          ),        
      ),
		));

If you want to see the entire Message.php model, visit it on Github.

Using Checkboxes with CGridView

The following code is how I implemented a checkbox column in a CGridView with Select All and an action button; no Javascript was required. This example is from Filtered, my open source IMAP mail filtering application.

yii_cgridview_checkbox

Controller

public function actionIndex()
	{
	  $this->layout = '//layouts/column1';
	  $model=new Sender('search');  		  	
          // detects the checkboxes
	  if(isset($_POST['sender-grid_c0']) and !empty($_POST['Sender']['folder_id']))
	  {
	    $dest_folder_id = $_POST['Sender']['folder_id'];
	    $sender_list = $_POST['sender-grid_c0'];
	    foreach ($sender_list as $sender_id) {
	      // train sender to folder_id
	      $model->setFolderCheckAccount($sender_id,$dest_folder_id);
	    }
	    Yii::app()->user->setFlash('trained','Your selections have been trained. Note: Trainings set to folders in the wrong account will be ignored.');
	    unset($_POST['Sender']['folder_id']);
		} 
  		$model->unsetAttributes();  // clear any default values
  		$model->user_id = Yii::app()->user->id;      		
  		$model->folder_id = 0;
                // since CGridView is in a form, we need to check GET & POST
                // to maintain filtering variables and sorting
  		if(isset($_GET['Sender']))
  			$model->attributes=$_GET['Sender'];
  		else if(isset($_POST['Sender']))
  			$model->attributes=$_POST['Sender'];
  		$this->render('index',array(
  			'model'=>$model->owned_by(Yii::app()->user->id),
  		));
	}

View

// Place the CGridView in a form, for posting from the action button
<?php $form=$this->beginWidget('bootstrap.widgets.TbActiveForm',array(
	'id'=>'sender-form',
	'enableAjaxValidation'=>false,
)); ?>

<?php $this->widget('bootstrap.widgets.TbGridView',array(
	'id'=>'sender-grid',
	'dataProvider'=>$model->untrained()->search('message_count desc'),
	'filter'=>$model,
	'columns'=>array(
// Use CCheckbox column with selectableRows = 2 for Select All
    array('class'=>'CCheckBoxColumn','selectableRows'=>2),
    array(            
                'name'=>'account_name',
                'header'=>'Account',
                'filter'=>CHtml::dropDownList(
                                                'Sender[account_name]',
                                                $model->account_name,
                                                CHtml::listData(
                                                        Account::model()->findAll(),
                                                        'name',
                                                        'name'),array('empty' => 'All')),                
                'value'=>'$data->account_name',
            ),
		'personal',
		'email',
  	array('class'=>'CDataColumn','name'=> 'message_count', 'header'=>'# Msgs','htmlOptions'=>array('width'=>'25px')),
		array(
			'class'=>'bootstrap.widgets.TbButtonColumn',
    	'header'=>'Options',
      'template'=>'{update}{delete}',
		),
	),
)); ?>
<?php echo CHtml::activeLabel($model,’folder_id’,array(‘label’=>’Train to Folder:’)); echo CHtml::activeDropDownList($model,’folder_id’,Sender::model()->getFolderOptions(),array(’empty’=>’Select a Folder’)); echo ‘ ‘; // action button $this->widget(‘bootstrap.widgets.TbButton’, array( ‘buttonType’=>’submit’, ‘type’=>’primary’, ‘label’=>’Save’, )); ?>
<?php $this->endWidget(); ?>