CGridView, urlManager, module conflict

Everything works fine until I set urlFormat to PATH. When I do that I encounter a problem that I can’t seem to figure out.

I have an admin module, and am using a CGridView there. Unfortunately, when I use the grid with a specific series of tasks, it breaks.

The series is:

a ) Set a filter

b ) Use the pager

c ) Set a filter

When done in that specific order, I get an error. After some research on these forums, I found a solution from GSTAR to add the following rule to my urlManager.


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

This works beautifully, and I have no errors, but the url path I get in the admin module is ugly:


admin/job/edit?=xxxxxx

I wanted to get rid of the "?=", so I changed the urlManager rule to:


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

This worked perfectly, except that view buttons in grids on the frontend broke as a result. They look accurate, but when clicking on them, they don’t go anywhere, so I reverted that urlManager rule:


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

And added this rule before it:


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

And this brings us back to square one where doing that specific series of tasks on admin grids breaks.

Any ideas?

I’m using something like this for the urlManager configuration.




'urlManager'=>array(

	'urlFormat'=>'path',

	'showScriptName' => false,

	'rules'=>array(

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

		'<_c:\w+>/<id:\d+>/<_a:(update|delete)>' => '<_c>/<_a>',

		'<_c:\w+>/<_a:\w+>' => '<_c>/<_a>',

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

		'<_m>/<_c:\w+>/<id:\d+>/<_a:(update|delete)>' => '<_m>/<_c>/<_a>',

		'<_m>/<_c:\w+>/<_a:\w+>' => '<_m>/<_c>/<_a>',

	),

),



If you are using the CRUD codes generated by Gii, without much customization, I hope this will help you.

<BTW>

I don’t see much points in so-called “SEO friendly” urls, especially when they are administrative pages.

</BTW>

[EDIT]

I’m using something like the following now.

It’s better to list the rules in the order of “from specific to general”. So the rules for the modules come first.




'urlManager'=>array(

	'urlFormat'=>'path',

	'showScriptName' => false,

	'rules'=>array(

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

		'<_m>/<_c:\w+>/<id:\d+>/<_a:(update|delete)>' => '<_m>/<_c>/<_a>',

		'<_m>/<_c:\w+>/<_a:\w+>' => '<_m>/<_c>/<_a>',

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

		'<_c:\w+>/<id:\d+>/<_a:(update|delete)>' => '<_c>/<_a>',

		'<_c:\w+>/<_a:\w+>' => '<_c>/<_a>',

	),

),



It is working fine.

Unfortunately, this solution didn’t do it for me, but I appreciate the attempt. I have a lot of actions, so my code and future updates would become inefficient if I tried to name them all.

SEO friendly urls on the frontend do help push the page to its maximum optimization, plus they make it more enticing for other sites to link to one of your pages, which can be a big bonus to your ranking. They are useless on the backend, however, so I ended up just leaving it alone. I was simply frustrated by the lack of consistency and didn’t want to settle for “ok” if it could look even better. I’ll leave this ticket open in case anyone does find a solution.

I apologize you if I mistake you, but have you considered using the "parameterized routs" explained in the guide?

THE DEFINITIVE GUIDE TO YII > URL Management > 4. parameterizing routs.

I don’t believe that you have to name all the modules/controllers/actions.

I would have to name each of the possible actions, no? That’s a problem for me, because I have far more than the actions initially generated by Gii.

No, you just have to tell the urlManager only the "possible patterns" of your modules/controllers/actions/parameters.

I hope that those of yours can be categorized into a several number of patterns and you can write them down to a decent set of urlManager rules.

But by "possible patterns", are you referring to this?


'<_m>/<_c:\w+>/<_a:(update|delete|view|etc.)>' => '<_m>/<_c>/<_a>',

From what I understand, the “etc.” there would need to be replaced by every other possible action, no? When I do this, that seems to be the only way to get it to work. The problem is that I have tons of actions, and I’m constantly adding more, so even limiting it to this one rule would be inefficient.

If I’m understanding this wrong, please let me know.

I think I myself need some help from an experienced member on this matter.

But now I think I’ve got your concerns somehow. Please forgive my stupidness.


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

has served you right in the ‘admin’ module on the back end, but has broken the links of CGridView buttons on the front end. Right?

It’s because a created path for the CGridView button (e.g. ‘foo/view/9’) fell into the pattern and routed to a non-existent route (i.e. ‘foo’ module’s ‘view’ controller’s ‘9’ action).

So I think now


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

in your first post should be the reasonable solution so far.

It works fine because it will not catch those patterns of front end while it catches all those patterns that belong to the ‘admin’ module.

You seem to be worrying about the CGridView functionality on this matter, but it’s not the problem between CGridView and urlManager. It’s a conflict between non-moduled paths and moduled paths in the urlManagers’s rules.

So, once again, I hope you can come up with only a decent number of patterns even if you have tons of actions.

Thanks,

I was having the same issue. Your first line of code worked for me. Did you find a way to keep the path format in the Admin module?

Cheers,

Matt

Try this




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

    'dataProvider' => $dataProvider,

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

    ...



ajaxUrl - set proper url for your page

Hi,

I got the problem solved!

I consider this as a framework level bug and I made some changes to framework/base/CApplication.php and I got everything

working as normal. Go there and fix function called createUrl, copy paste this there and change your own controller

name instead of mines. Also put the correct substr parameters, it should be the length of

yourController/admin string.




	public function createUrl($route,$params=array(),$ampersand='&')

	{

		

		//This hack is made by paulusmikkola@hotmail.com. Yii seems to have module conflict with CGridview and UrlManager

		$newParams = array();

		foreach($params as $key => $p)

		{

			//insert your own controller + /admin instead of "person/admin" and "invoice/admin"

			if(substr($key, 0, 12) != "person/admin" && substr($key, 0, 13) != "invoice/admin")

			{

				$newParams[$key] = $p;

			}		

		}

		$params = $newParams;

		//end of hack

		

		return $this->getUrlManager()->createUrl($route,$params,$ampersand);

	}




You know this is not correct solution, but works. It could conflick with some URL:s, but works in my app.

I hope Yii crew look for framework level bug fixs for this problem, becouse mine is not dynamic and well made. It seems that in some reason the first paramater of createUrl function $params is repeating almost the whole url address and my bug fix just drop this parameter.

Let me know if you get this one work.

It was the solution for my problem, very thanks