CActiveDataProvider and grid.CGridView

Hey guys, I’m battling CActiveDataProvider and I’m losing it.

I need to display a list of customer with Status "New" and the list should be sorted in descending order of customer_id.

Problem is, no matter what I do with CActiveDataProvider I cant seem to make it work. I either take away the search() and it stops filtering the grid or I add the search() and the grid gets resorted by the search()

Controller





public function actionRegistered()

	{

		

		

		$criteriaPrivate=new CDbCriteria;

		$criteriaPrivate->addcondition('status="New"');		

		

		$dataProvider = new CActiveDataProvider('Client', array(

				'criteria'=>$criteriaPrivate,

				'pagination' => array('pageSize' => 30,),


				'sort'=>array(

						'defaultOrder'=>'customer_id DESC',

					),				

			)

		

		);


		

		

		$model = new Client('search');

		//$model->status='New';	

		$model->groupsize='';	

		//$model->customer_id;

		//$model ->unsetAttributes();

		if(isset($_GET['Client']))

			$model->attributes=$_GET['Client'];

			

		$this->render('registered', array(

				'dataProvider'=>$dataProvider,

				'model'=>$model,				

			)

		

		);

		

		

		

		

	}



View




<?php $this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'customer_id',		

	'dataProvider'=>$dataProvider,

	'filter'=>$model,

	'enablePagination'=>true,	

	'columns'=>array(

		//'customer_id',

		'fname',

		'lname',			

		'email',

		'phone',

		'groupsize',

		'date_created',		

		 array(

			'class'=>'CButtonColumn',

			'template'=>'{update}',

			'updateButtonUrl'=>'Yii::app()->controller->createUrl("/client/waitingupdate",array("id"=>$data["customer_id"]))',

			'updateButtonImageUrl'=>'',

		),	

	),

));?>




Any ideas on what can I do?

try this code for your action (modified from yours):

note:

you dont need the search() model method if the query is so simple as filtering by one or two fields,




    public function actionRegistered($pageSize = 20)

    {

		// your criteria

		$criteriaPrivate = 'newrecord = 1';

		

		$dataProvider new CActiveDataProvider('Client', array(

    		'criteria'=>array(

           		'condition'=>$criteriaPrivate,

    		),

    		'pagination'=>array(

        		'pageSize'=>$pageSize,

    		),

    		'sort'=>array(

    			'defaultOrder'=>array('customer_id'=>true),

    		),

		));			

    	

      // the model...is not necesary in your view for this case (remove the reference from your view)

 	// $model = new Client();


		// this is fine:

		$this->render('registered'

			, array('dataProvider'=>$dataProvider   /*,'model'=>$model */  ) );

	}



Sorry didnt reply right away but I’m getting this:




CActiveDataProvider and its behaviors do not have a method or closure named "getValidators".


C:\wamp\www\yii\framework\base\CComponent.php(266)


254     public function __call($name,$parameters)

255     {

256         if($this->_m!==null)

257         {

258             foreach($this->_m as $object)

259             {

260                 if($object->getEnabled() && method_exists($object,$name))

261                     return call_user_func_array(array($object,$name),$parameters);

262             }

263         }

264         if(class_exists('Closure', false) && $this->canGetProperty($name) && $this->$name instanceof Closure)

265             return call_user_func_array($this->$name, $parameters);

266         throw new CException(Yii::t('yii','{class} and its behaviors do not have a method or closure named "{name}".',

267             array('{class}'=>get_class($this), '{name}'=>$name)));

268     }

269 

270     /**

271      * Returns the named behavior object.

272      * The name 'asa' stands for 'as a'.

273      * @param string $behavior the behavior name

274      * @return IBehavior the behavior object, or null if the behavior does not exist

275      */

276     public function asa($behavior)

277     {

278         return isset($this->_m[$behavior]) ? $this->_m[$behavior] : null;


Stack Trace

#0 	

+

 C:\wamp\www\yii\framework\web\helpers\CHtml.php(1758): CComponent->__call("getValidators", array("fname"))

#1 	

+

 C:\wamp\www\yii\framework\web\helpers\CHtml.php(1758): CActiveDataProvider->getValidators("fname")

#2 	

+

 C:\wamp\www\yii\framework\web\helpers\CHtml.php(1205): CHtml::activeInputField("text", CActiveDataProvider, "fname", array("name" => "CActiveDataProvider[fname]"))

#3 	

+

 C:\wamp\www\yii\framework\zii\widgets\grid\CDataColumn.php(105): CHtml::activeTextField(CActiveDataProvider, "fname", array("id" => false))

#4 	

+

 C:\wamp\www\yii\framework\zii\widgets\grid\CGridColumn.php(106): CDataColumn->renderFilterCellContent()

#5 	

+

 C:\wamp\www\yii\framework\zii\widgets\grid\CGridView.php(450): CGridColumn->renderFilterCell()

#6 	

+

 C:\wamp\www\yii\framework\zii\widgets\grid\CGridView.php(428): CGridView->renderFilter()

#7 	

+

 C:\wamp\www\yii\framework\zii\widgets\grid\CGridView.php(398): CGridView->renderTableHeader()

#8 	

+

 C:\wamp\www\yii\framework\zii\widgets\CBaseListView.php(158): CGridView->renderItems()

#9 	

 unknown(0): CBaseListView->renderSection(array("{items}", "items"))

#10 	

+

 C:\wamp\www\yii\framework\zii\widgets\CBaseListView.php(141): preg_replace_callback("/{(\w+)}/", array(CGridView, "renderSection"), "{summary} {items} {pager}")

#11 	

+

 C:\wamp\www\yii\framework\zii\widgets\CBaseListView.php(126): CBaseListView->renderContent()

#12 	

+

 C:\wamp\www\yii\framework\web\CBaseController.php(174): CBaseListView->run()

#13 	

–

 C:\wamp\www\******\protected\views\client\registered.php(162): CBaseController->widget("zii.widgets.grid.CGridView", array("id" => "customer_id", "dataProvider" => CActiveDataProvider, "filter" => CActiveDataProvider, "enablePagination" => true, ...))


157             'template'=>'{update}',

158             'updateButtonUrl'=>'Yii::app()->controller->createUrl("/client/waitingupdate",array("id"=>$data["customer_id"]))',

159             'updateButtonImageUrl'=>'',

160         ),    

161     ),

162 ));?>

163 

164 

165 


#14 	

+

 C:\wamp\www\yii\framework\web\CBaseController.php(127): require("C:\wamp\www\******\protected\views\client\registered...")

#15 	

+

 C:\wamp\www\yii\framework\web\CBaseController.php(96): CBaseController->renderInternal("C:\wamp\www\******\protected\views\client\registered...", array("dataProvider" => CActiveDataProvider), true)

#16 	

+

 C:\wamp\www\yii\framework\web\CController.php(870): CBaseController->renderFile("C:\wamp\www\******\protected\views\client\registered...", array("dataProvider" => CActiveDataProvider), true)

#17 	

+

 C:\wamp\www\yii\framework\web\CController.php(783): CController->renderPartial("registered", array("dataProvider" => CActiveDataProvider), true)

#18 	

–

 C:\wamp\www\******\protected\controllers\ClientController.php(335): CController->render("registered", array("dataProvider" => CActiveDataProvider))


330       // the model...is not necesary in your view for this case (remove the reference from your view)

331         // $model = new Client();

332 

333                 // this is fine:

334                 $this->render('registered'

335                         , array('dataProvider'=>$dataProvider   /*,'model'=>$model */  ) );

336         }

337 

338 

339 

340     /*public function actionRegistered()


#19 	

 unknown(0): ClientController->actionRegistered(20)

#20 	

+

 C:\wamp\www\yii\framework\web\actions\CAction.php(107): ReflectionMethod->invokeArgs(ClientController, array(20))

#21 	

+

 C:\wamp\www\yii\framework\web\actions\CInlineAction.php(48): CAction->runWithParamsInternal(ClientController, ReflectionMethod, array())

#22 	

+

 C:\wamp\www\yii\framework\web\CController.php(309): CInlineAction->runWithParams(array())

#23 	

+

 C:\wamp\www\yii\framework\web\filters\CFilterChain.php(134): CController->runAction(CInlineAction)

#24 	

+

 C:\wamp\www\yii\framework\web\filters\CFilter.php(41): CFilterChain->run()

#25 	

+

 C:\wamp\www\yii\framework\web\CController.php(1146): CFilter->filter(CFilterChain)

#26 	

+

 C:\wamp\www\yii\framework\web\filters\CInlineFilter.php(59): CController->filterAccessControl(CFilterChain)

#27 	

+

 C:\wamp\www\yii\framework\web\filters\CFilterChain.php(131): CInlineFilter->filter(CFilterChain)

#28 	

+

 C:\wamp\www\yii\framework\web\CController.php(292): CFilterChain->run()

#29 	

+

 C:\wamp\www\yii\framework\web\CController.php(266): CController->runActionWithFilters(CInlineAction, array("accessControl", "ajaxOnly + data"))

#30 	

+

 C:\wamp\www\yii\framework\web\CWebApplication.php(276): CController->run("registered")

#31 	

+

 C:\wamp\www\yii\framework\web\CWebApplication.php(135): CWebApplication->runController("client/registered")

#32 	

+

 C:\wamp\www\yii\framework\base\CApplication.php(162): CWebApplication->processRequest()

#33 	

–

 C:\wamp\www\******\index.php(13): CApplication->run()


08 defined('YII_DEBUG') or define('YII_DEBUG',true);

09 // specify how many levels of call stack should be shown in each log message

10 defined('YII_TRACE_LEVEL') or define('YII_TRACE_LEVEL',3);

11 

12 require_once($yii);

13 Yii::createWebApplication($config)->run();






as your logs show, [size="3"]the view "registered", has an CGridView object, this object reference a field named "fname" on an object of class "Client".

Is "fname" an attribute in your model Client ?[/size]

[size="3"]

[/size]

[size=2]copy your Client.php file here, and the registered.php view here too.[/size]

yes its a field in the database and model.

Registered:




<?php

$this->breadcrumbs=array(

	'Clients'=>array('index'),

	'Manage',

);


$this->menu=array(

	array('label'=>'List Client', 'url'=>array('index')),

	array('label'=>'Create Client', 'url'=>array('create')),

);


<h1>Registered Customers</h1>


<p>

You may optionally enter a comparison operator (<b>&lt;</b>, <b>&lt;=</b>, <b>&gt;</b>, <b>&gt;=</b>, <b>&lt;&gt;</b>

or <b>=</b>) at the beginning of each of your search values to specify how the comparison should be done.

</p>




<?php $this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'customer_id',		

	'dataProvider'=>$dataProvider,

	'filter'=>$dataProvider,

	'enablePagination'=>true,	

	'columns'=>array(

		//'customer_id',

		'fname',

		'lname',			

		'email',

		'phone',

		'groupsize',

		'date_created',		

		 array(

			'class'=>'CButtonColumn',

			'template'=>'{update}',

			'updateButtonUrl'=>'Yii::app()->controller->createUrl("/client/waitingupdate",array("id"=>$data["customer_id"]))',

			'updateButtonImageUrl'=>'',

		),	

	),

));?>




ClientController

I will just put the registered action. I dont want to make the whole application public.





public function actionRegistered($pageSize = 20)

    {

                // your criteria

                $criteriaPrivate = 'status = "New"';

                

                $dataProvider = new CActiveDataProvider('Client', array(

                'criteria'=>array(

                        'condition'=>$criteriaPrivate,

                ),

                'pagination'=>array(

                        'pageSize'=>$pageSize,

                ),

                'sort'=>array(

                        'defaultOrder'=>array('customer_id'=>true),

                ),

                ));                     

        

      // the model...is not necesary in your view for this case (remove the reference from your view)

        // $model = new Client();


                // this is fine:

                $this->render('registered'

                        , array('dataProvider'=>$dataProvider   /*,'model'=>$model */  ) );

	}



is not necesary publish the whole application, only the fields on your [color=#008800][size=2]Clients [/size][/color]model, because its seems the problem is here: a bad attribute name reference,

publish only the model attributes, and the rules() method.

the controller and view are ok.

hello, try commenting the entire array(…) column in your CGridView,

i see a $data , and it is not passed in the array data from the controller.

array(class’=>‘CButtonColumn’,

‘template’=>’{update}’, ‘updateButtonUrl’=>‘Yii::app()->controller->createUrl("/client/waitingupdate",array(“id”=>[color="#ff0000"]$data[/color][“customer_id”]))’,

no its not it. I think $data is just any variable that would hold the link to the Client.

I have tried your suggestion and it gives the same error.

I looked around and commented the filter function of CGridView

Here is the look at it:





<?php $this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'customer_id',		

	'dataProvider'=>$dataProvider,

	//'filter'=>$dataProvider,

	'enablePagination'=>true,	

	'columns'=>array(

		//'customer_id',

		'fname',

		'lname',			

		'email',

		'phone',

		'groupsize',

		'date_created',		

		 array(

			'class'=>'CButtonColumn',

			'template'=>'{update}',

			'updateButtonUrl'=>'Yii::app()->controller->createUrl("/client/waitingupdate",array("id"=>$data["customer_id"]))',

			'updateButtonImageUrl'=>'',

		),	

	),

));?>


is there a way of having the filter actually work?



Here are my rules()





public function rules()

	{

		// NOTE: you should only define rules for those attributes that

		// will receive user inputs.

		return array(

			array('phone, fname, lname, email', 'required'),

			array('groupsize', 'numerical', 'integerOnly'=>true),

			array('phone, email', 'length', 'max'=>30),

			array('fname, lname', 'length', 'max'=>40),

			array('smsnotification, emailnotification', 'length', 'max'=>3),

			array('status', 'length', 'max'=>15),

			array('verifyCode', 'captcha', 'allowEmpty'=>!CCaptcha::checkRequirements(), 'on'=>'register'),

			// The following rule is used by search().

			// Please remove those attributes that should not be searched.

			array('customer_id, phone, fname, lname, email, smsnotification, emailnotification, status, groupsize, date_created', 'safe', 'on'=>'search'),

		);

	}




My search():




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('phone',$this->phone,true);

		$criteria->compare('fname',$this->fname,true);

		$criteria->compare('lname',$this->lname,true);

		$criteria->compare('email',$this->email,true);

		$criteria->compare('smsnotification',$this->smsnotification,true);

		$criteria->compare('emailnotification',$this->emailnotification,true);

		$criteria->compare('status',$this->status,true);

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

		$criteria->compare('date_created',$this->date_created,true);


		return new CActiveDataProvider($this, array(

			'criteria'=>$criteria,

		));

	}



Btw…thanks so much for helping. I’m pretty new to Yii and really need guidance about these things.

Why did you change your filter from $model to $dataProvider?

In your post #1:


'filter'=>$model,

and then in your post #5:


'filter'=>$dataProvider,

(and then you comment it out)

Hi psolovyov,

Did you solve the probelm?

I would do like this:




// controller

public function actionRegistered()

{

	$model = new Client('search');

	$model->unsetAttributes();

	$model->status='New'; 


	if(isset($_GET['Client']))

		$model->attributes=$_GET['Client'];


	$this->render('registered', array(

		'model'=>$model,

	));

}


// model

public function search()

{

	$criteria=new CDbCriteria;


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

	$criteria->compare('phone',$this->phone,true);

	$criteria->compare('fname',$this->fname,true);

	$criteria->compare('lname',$this->lname,true);

	$criteria->compare('email',$this->email,true);

	$criteria->compare('smsnotification',$this->smsnotification,true);

	$criteria->compare('emailnotification',$this->emailnotification,true);

	$criteria->compare('status',$this->status, true);

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

	$criteria->compare('date_created',$this->date_created,true);


	return new CActiveDataProvider($this, array(

		'criteria'=>$criteria,

		'pagination'=>array(

			'pageSize'=>30,

		),

		'sort'=>array(

			'defaultOrder'=>'customer_id DESC',

		),

	));

}


// view

$this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'customer_id',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'enablePagination'=>true,

	'columns'=>array(

		'customer_id', // ... you may comment it out if you don't want it

		'fname',

		'lname',                        

		'email',

		'phone',

		'groupsize',

		'date_created',         

		array(

			'class'=>'CButtonColumn',

			'template'=>'{update}',

			'updateButtonUrl'=>'Yii::app()->controller->createUrl("/client/waitingupdate",array("id"=>$data->customer_id))',

			'updateButtonImageUrl'=>'',

		),      

	),

));



Not very much modified from the gii-generated admin page. But it should work, I hope.

One of the points is this:




			'updateButtonUrl'=>'Yii::app()->controller->createUrl("/client/waitingupdate",array("id"=>$data->customer_id))',



Look it up in the reference of CButtonColumn::updateButtonUrl.

http://www.yiiframework.com/doc/api/1.1/CButtonColumn/#updateButtonUrl-detail

‘$data’ is the model (in this case ‘Customer’) in the expression, and you can retrieve the customer_id by $data->customer_id, not by $data[‘customer_id’].

[color=#000000]

[/color][color=#666600]<?[/color][color=#000000]php $this[/color][color=#666600]->[/color][color=#000000]widget[/color][color=#666600]([/color][color=#008800]‘zii.widgets.grid.CGridView’[/color][color=#666600],[/color][color=#000000] array[/color][color=#666600]([/color][color=#000000]

    [/color][color=#008800]'id'[/color][color=#666600]=&gt;[/color][color=#008800]'customer_id'[/color][color=#666600],[/color][color=#000000]            


    [/color][color=#008800]'dataProvider'[/color][color=#666600]=&gt;[/color][color=#000000]&#036;dataProvider[/color][color=#666600],[/color][color=#000000]


    [/color][color=#880000]//'filter'=&gt;&#036;dataProvider,[/color][color=#000000]


    [/color][color=#008800]'enablePagination'[/color][color=#666600]=&gt;[/color][color=#000088]true[/color][color=#666600],[/color][color=#000000]       


    [/color][color=#008800]'columns'[/color][color=#666600]=&gt;[/color][color=#000000]array[/color][color=#666600]([/color][color=#000000]


            [/color][color=#880000]//'customer_id',[/color][color=#000000]


            [/color][color=#008800]'fname'[/color][color=#666600],[/color][color=#000000]


            [/color][color=#008800]'lname'[/color][color=#666600],[/color][color=#000000]                        


            [/color][color=#008800]'email'[/color][color=#666600],[/color][color=#000000]


            [/color][color=#008800]'phone'[/color][color=#666600],[/color][color=#000000]


            [/color][color=#008800]'groupsize'[/color][color=#666600],[/color][color=#000000]


            [/color][color=#008800]'date_created'[/color][color=#666600],[/color][color=#000000]         [/color][color=#000000]

[/color][color=#000000]/* as i said before, i suggest you comment this entire piece of code and look for $data, whats is data in your system ?[/color][color=#000000]

[/color][color=#000000]

             array[/color][color=#666600]([/color][color=#000000]


                    [/color][color=#008800]'class'[/color][color=#666600]=&gt;[/color][color=#008800]'CButtonColumn'[/color][color=#666600],[/color][color=#000000]


                    [/color][color=#008800]'template'[/color][color=#666600]=&gt;[/color][color=#008800]'{update}'[/color][color=#666600],[/color][color=#000000]


                    [/color][color=#008800]'updateButtonUrl'[/color][color=#666600]=&gt;[/color][color=#008800]'Yii::app()-&gt;controller-&gt;createUrl(&quot;/client/waitingupdate&quot;,array(&quot;id&quot;=&gt;&#036;data[&quot;customer_id&quot;]))'[/color][color=#666600],[/color][color=#000000]


                    [/color][color=#008800]'updateButtonImageUrl'[/color][color=#666600]=&gt;[/color][color=#008800]''[/color][color=#666600],[/color][color=#000000]


            [/color][color=#666600]),[/color][color=#000000]      [/color][color=#000000]*/


    [/color][color=#666600]),[/color][color=#000000]

[/color][color=#666600]));?>[/color]

@bluyell

You seem to have overlooked CButtonColumn::updateButtonUrl, and what $data means in its expression. :)

$data[‘customer_id’] is a problem for sure, but $data itself is not a problem at all.

Please take a look at the last portion of my previous post.

Thanks!!! This worked!!!!!!

Thanks to everybody who helped out here. I had a bunch of projects on the go so I couldn’t reply right away to the posts.