CGridView generates wrong url for filter ajax requests

Hi,

problem appears only if i use ‘urlFormat’=>‘path’. urlManager configuration:




		'urlManager'=>array(

			'urlFormat'=>'path',

            'showScriptName'=>false,

			'rules'=>array(

			),

		),



I also did try adding rules, this didn’t help:




'<controller:\w+>/<action:\w+>/*' => '<controller>/<action>',

'<controller:\w+>/<action:\w+>' => '<controller>/<action>',



CGridView generates urls like this for filter ajax requests:


http://site.com/metadatatype/admin/MetadataType_sort/name?ajax=yw0&MetadataType%5Bid%5D=5&MetadataType%5Bname%5D=&MetadataType%5Bdesc%5D=&MetadataType_page=1

Those urls are wrong and filtering doesn’t work for me.

What are all those symbols "%5B %5D %5B" for?

I am also getting strange urls from sorting and paginator. Wrong paginator url example:




http://site.com/metadatatype/admin/%2Fmetadatatype//MetadataType_page/2



Wrong sorting url example:




http://site.com/metadatatype/admin/%2Fmetadatatype//MetadataType_sort/name



If i set params to empty arrays i will get correct urls for paginator and sorting:




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


            'pagination' => array(

                'params' => array(),

                'pageSize' => 4,

            ),

            'sort' => array(

                'params' => array(),

                'defaultOrder' => array('id' => false),

            )

        ));



How can i get correct urls for filter?

Thanks

Did you try default yii rules?




	'<controller:\w+>/<id:\d+>'=>'<controller>/view',

	'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

	'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',



Yes, but it didn’t help… It still forms request urls like this:




http://site.com/metadatatype?MetadataType%5Bid%5D=4&MetadataType_page=1&ajax=yw0



Maybe i am doing something wrong. There is my action code:




	public function actionAdmin()

	{

        $model = new MetadataType('search');

        $model->unsetAttributes(); // clear any default values


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

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


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


            'pagination' => array(

                'params' => array(),

                'pageSize' => 4,

            ),

            'sort' => array(

                'params' => array(),

                'defaultOrder' => array('id' => false),

            )

        ));


		$this->render('admin/admin',

            array(

                'dataProvider'=>$dataProvider,

                'model'=>$model,

            )

        );

	}



View:




<?php


$columns[]=array(

    'name'=>'id',

    'filter'=>CHtml::activeTextField($model,'id'),

    'header'=>'Id',

);





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

    array('dataProvider' => $dataProvider,

       'columns'=>$columns,

        'filter' => $model,

    ))


?>



Model->search():




	public function search() {

		$criteria = new CDbCriteria;


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

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

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


		return new CActiveDataProvider($this, array(

			'criteria' => $criteria,

		));

	}



still looking for solution…

I think you need this:




        $dataProvider = new CActiveDataProvider($model->search(), ...



Tried this one, thanks, but got error. Code:




public function actionAdmin()

	{

        $model = new MetadataType('search');

        $model->unsetAttributes(); // clear any default values


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

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


        $dataProvider = new CActiveDataProvider($model->search(), array(


            'pagination' => array(

                'params' => array(),

                'pageSize' => 4,

            ),

            'sort' => array(

                'params' => array(),

                'defaultOrder' => array('id' => false),

            )

        ));


		$this->render('admin/admin',

            array(

                'dataProvider'=>$dataProvider,

                'model'=>$model,

            )

        );

	}



Error:




Fatal error: Call to a member function getDbCriteria() on a non-object in E:\Dropbox\web\_frameworks\yii\framework\web\CActiveDataProvider.php on line 173



Also tried this:




	public function actionAdmin()

	{

        $model = new MetadataType('search');

        $model->unsetAttributes(); // clear any default values


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

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


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


            'model'=>$model,


            'pagination' => array(

                'params' => array(),

                'pageSize' => 4,

            ),

            'sort' => array(

                'params' => array(),

                'defaultOrder' => array('id' => false),

            )

        ));


		$this->render('admin/admin',

            array(

                'dataProvider'=>$dataProvider,

                'model'=>$model,

            )

        );

	}



Action works without errors, but filtering doesn’t work.

Do you have search() method in your MetadataType model ? If not you need to add it. It may return CActiveDataProvider itself, then you need not create dataProvider in controller’s action. Try to look at some of the wiki pages:

http://www.yiiframework.com/wiki/117/using-standard-filters-in-cgridview-custom-fields/

Yes, i got this method. The implementation is pretty standart:




	public function search() {

		$criteria = new CDbCriteria;


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

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

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


		return new CActiveDataProvider($this, array(

			'criteria' => $criteria,

		));

	}



I stucked at this code, controller:




	public function actionAdmin()

	{

        $model = new MetadataType('search');

        $model->unsetAttributes(); // clear any default values


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

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


        $dataProvider=$model->search();


        $dataProvider->setSort(array(

            'params' => array(),

            'defaultOrder' => array('id' => false)));

        $dataProvider->setPagination(array(

            'params' => array(),

            'pageSize' => 4,

        ));


 		$this->render('admin/admin',

            array(

                'dataProvider'=>$dataProvider,

                'model'=>$model,

            )

        );

	}



View:




$columns[]=array(

    'name'=>'id',

    'filter'=>CHtml::activeTextField($model,'id'),

    'header'=>'Id',

);


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

    array('dataProvider' => $dataProvider,

       'columns'=>$columns,

        'filter' => $model,

    ));



This code works fine: filtering, sorting, paginator - all work correct. But it works only if i am not using ‘urlFormat’=>‘path’. If i turn on ‘path’ url-format, sorting and paginator work, filtering - not.

I did try ‘urlFormat’=>‘path’:

[list=1]

[*]without rules - filtering doesn’t work;

[]with rule '<controller:\w+>/<action:\w+>/’ => ‘<controller>/<action>’ - filtering doesn’t work;

[*]with rule ‘<controller:\w+>/<action:\w+>’ => ‘<controller>/<action>’ - sorting, paginator and filtering not work;

[/list]

It looks like problem is with urlManager. What am i doing wrong? I also use nginx.

Any ideas ?

Try this




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

    'dataProvider' => $dataProvider,

    'ajaxUrl' => $this->createUrl('index'),

    ...



ajaxUrl - set proper url for your page and remove all rules in urlManager

Hi, thanks for replay. I did try ajaxUrl, but nothing changed, still generate wrong urls…

Yes, it generate non path urls for ajax requests, but filtering working fine after using sorting or pager.

I don’t know why, but in my case it is not working even after using sorting or paging :(

Is there any way to turn on generating path-like urls for ajax-requests in CGridView?

You should use those rules http://code.google.com/p/yii/issues/detail?id=1335

I had the same problem yesterday, the get vars from ajax messed up the url…

In my case it’s was fixed by using ajaxUrl, but it’s not ideal…

Just tried them




'<controller:\w+>/<id:\d+>'=>'<controller>/view',

'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',



Sorting and paginator stoped work (filtering too). Qiang Xue said that this is impossible to fix because js can’t provide url manager logic. I don’t need url-rules to be applied to ajax request urls (in my case), but only path-like urls:


requestUrl/parameter1Name/parameter1Value/parameter2Name/parameter2Value/etc ...

:mellow:

Maybe problem is cased by incorrect configured nginx. There is my configuration:




server {

          listen       127.0.0.77; 

   

          server_name  site.com;

          charset utf-8; 

   

          root "e:/Dropbox/web/site"; 


            location / {

            try_files $uri $uri/ @php;

            index index.php;

            }


            location @php {

            fastcgi_pass 127.0.0.1:9123;

            fastcgi_param SCRIPT_FILENAME $document_root/index.php;

            fastcgi_param QUERY_STRING $uri;

            include fastcgi_params1;

            }


            location ~ \.php$ {

            fastcgi_pass 127.0.0.1:9123;

            fastcgi_param SCRIPT_FILENAME $document_root/$uri;

            fastcgi_param QUERY_STRING $args;

            include fastcgi_params1;

            }          

    }



"fastcgi_params1" file:




fastcgi_param  REQUEST_METHOD     $request_method;

fastcgi_param  CONTENT_TYPE       $content_type;

fastcgi_param  CONTENT_LENGTH     $content_length; 

 

fastcgi_param  SCRIPT_NAME        $fastcgi_script_name;

fastcgi_param  REQUEST_URI        $request_uri;

fastcgi_param  DOCUMENT_URI       $document_uri;

fastcgi_param  DOCUMENT_ROOT      $document_root;

fastcgi_param  SERVER_PROTOCOL    $server_protocol; 

 

fastcgi_param  GATEWAY_INTERFACE  CGI/1.1;

fastcgi_param  SERVER_SOFTWARE    nginx/$nginx_version; 

 

fastcgi_param  REMOTE_ADDR        $remote_addr;

fastcgi_param  REMOTE_PORT        $remote_port;

fastcgi_param  SERVER_ADDR        $server_addr;

fastcgi_param  SERVER_PORT        $server_port;

fastcgi_param  SERVER_NAME        $server_name; 


 

# PHP only, required if PHP was built with --enable-force-cgi-redirect

fastcgi_param  REDIRECT_STATUS    200; 




fastcgi_connect_timeout 60;

fastcgi_send_timeout 180;

fastcgi_read_timeout 180;

fastcgi_buffer_size 128k;

fastcgi_buffers 4 256k;

fastcgi_busy_buffers_size 256k;

fastcgi_temp_file_write_size 256k;

fastcgi_intercept_errors on;



If somebody is using nginx with ‘urlFormat’=>‘path’, please share your configuration, thanks.

It not ideal maybe, but it best in this case. No need any rules for normal working.

For ideal solutions it need working with CGridview widget for make it send ajax request in path mode.

I have the same problem and make a little investigation and find, that the reason is a merging slashes in url ("/" instead "//"), this cause invalid $_GET parameters, and so on.

Set “merge_shashes off” in your nginx configuration in server context. I think, it will solve your problem. I will try this tomorrow, too. :)

hello smck,

That admin is in inside of a module? because i had the same problem, and i solved adding this line in main.php, inside of the url manager:


'moduleName/<controller:\w+>/<action:\w+>' => 'moduleName/<controller>/<action>' 

where, of course, ‘moduleName’ i put my module name. Try it, and tell how you go with it…

Hi all, in my case, specifying the module’s name does solve the problem.