How to custom url

Hi, I’m working on one application where we need to have some custom url with these examples.

mydomain.com/toronto/free-wifi-restaurants.htm

parameters =toronto, free-wifi

mydomain.com/toronto/sushi-restaurants.htm

parameters =toronto, sushi

mydomain.com/toronto/downtown-restaurants.htm

parameters =toronto, downtown

in my config.php files




$retval=array(

		

        'urlManager'=>array(

            'urlFormat'=>'path',

            'showScriptName'=>false,

            'urlSuffix'=>'.htm',

            'rules'=>require(dirname(__FILE__).DIRECTORY_SEPARATOR.'routes.php'),

        ),

)



in my routes.php file




$retval=array(

		

	'<cityAlias:.*?>-<featureAlias:.*?>-restaurants'=>'restaurants/showByFeatures',

	'<cityAlias:.*?>-<foodAlias:.*?>-restaurants/'=>'restaurants/showByFoods',

	'<cityAlias:.*?>-<areaAlias:.*?>-restaurants'=>'restaurants/showByArea',

)



in my view.php file




$retval=array(

		

<?php echo CHtml::link('Free Wi-Fi', array('restaurants/showByFeatures','cityAlias'=>'toronto', 'featureAlias'=>'free-wifi'));?>	


<?php echo CHtml::link('Sushi', array('restaurants/showByFoods','cityAlias'=>'toronto', 'foodAlias'=>'Sushi'));?>	


<?php echo CHtml::link('Free Wi-Fi', array('restaurants/showByFeatures','cityAlias'=>'toronto', 'areaAlias'=>'downtown'));?>	

)



My problem is if I keep all above url routes together then some of them get route to wrong controller/action but if I remove two and keep one then it works as we per result.

Any idea where we doing mistake and some alternate for this task.

I look forward to hear from you guys,

Jan

Just remove :.*? from the rules.


'<cityAlias>-<featureAlias>-restaurants'=>'restaurants/showByFeatures',

If that doesn’t work, change the dashes with slashes.

IMO, it would be more consistent if you used slashes.

Also, Google seems to handle dashes badly.

Another argument in favor of slashes is that users can easily change the url:

[color="#1C2837"] [/color]




mydomain.com/toronto/downtown/restaurants/

mydomain.com/toronto/downtown/hotels/

mydomain.com/toronto/uptown/restaurants/



All of your rules are the same (left part), so only the 1st rule will work when parsing url. You have 2 options:

  1. Make more specific rules, e.g.:



'<cityAlias:.*?>-<featureAlias:(free-wifi|another-feature)>-restaurants'=>'restaurants/showByFeatures',

'<cityAlias:.*?>-<foodAlias:(sushi|another-food)?>-restaurants/'=>'restaurants/showByFoods',



  1. Use only 1 rule and do all job in action "show".

Actually there can be more options, but these two are the most obvious and easy.

jacmoe, I did use both your ideas like remove :.*? or replace / with - but it doesnt change any things as a result same like some works and some routing to different action in controller.

For andy_s suggestion for below codes, as food categories and features can be more as we have to define in route for each Foods or Features if so then this doesnt work for me as Food Category and Features getting more gradually.




'<cityAlias:.*?>-<featureAlias:(free-wifi|another-feature)>-restaurants'=>'restaurants/showByFeatures',

'<cityAlias:.*?>-<foodAlias:(sushi|another-food)?>-restaurants/'=>'restaurants/showByFoods',



Any other solution will highly be appreciated as I have give up all the way by trying so finally come to here.

Jan

Strange. I have something similar going on …

However, if you fail to make this happen, then you could try custom rule classes:

http://www.yiiframework.com/doc/guide/1.1/en/topics.url#using-custom-url-rule-classes

Hi, I made it but like this

As some works and some route to different controller/action




        '<cityAlias:.*?>-<foodAlias:.*?>-restaurants/'=>'restaurants/showByFoods',

        '<cityAlias:.*?>-<areaAlias:.*?>-restaurants'=>'restaurants/showByArea',



change to this then two of them got works




        '<foodAlias:.*?>-<cityAlias:.*?>-restaurants/'=>'restaurants/showByFoods',

        '<cityAlias:.*?>-<areaAlias:.*?>-restaurants'=>'restaurants/showByArea',

 

What I did here is only replace the position of


<cityAlias>

with


<foodAlias:.*?>

and it works

But I dont like to be like this as the ‘City’ parameter should be first.

Any idea if some one can make some changes to get it works.

The rules (routes) will only work if you pass the right parameters to functions which accept the right parameters, which again means that they should be named the same.

Check that first.

jacmoe thanks for your all prompt replies and keep following this post for solving this issue, in regards to your question for passing right parameters to functions I did double check each single character and found all are ok as you can see here




        '<cityAlias:.*?>-<foodAlias:.*?>-restaurants/'=>'restaurants/showByFoods',

        '<cityAlias:.*?>-<areaAlias:.*?>-restaurants'=>'restaurants/showByArea',






<?php echo CHtml::link('downtown', array('restaurants/showByArea','cityAlias'=>'toronto', 'featureAlias'=>'downtown'));?>        

<?php echo CHtml::link('Sushi', array('restaurants/showByFoods','cityAlias'=>'toronto', 'foodAlias'=>'Sushi'));?>       



Anyway so far no luck to solve by this way, what about another way to design custom url class as you mentioned in your earlier post.

Do you have any step by step easy to understand as this might be helpful for to understand other newbie too and you will get all credits for this. :)

I look forward for your comments.

Use createUrl:


<?php echo CHtml::link('downtown', $this->createUrl('restaurants/showByArea', array('cityAlias'=>'toronto', 'featureAlias'=>'downtown')));?>

<?php echo CHtml::link('Sushi', $this->createUrl('restaurants/showByFoods', array('cityAlias'=>'toronto', 'foodAlias'=>'Sushi')));?>   	



The only first works but the second one goes to first one controller/action which is not correct.

The problem cause by ‘cityAlias’ parameter which is same and on 1 left position even if I change the parameter name from ‘cityAlias’ to ‘cityName’ also doesnt get effect.

The only thing which works is to change the position of ‘cityAlias’ with ‘restaurant’ text in url in example

from (toronto/restaurants/sushi.htm) to (restaurants/toronto/sushi.htm) then both links works.

Which is not good. :)

Do you have a restaurants controller with two actions actionShowByArea and actionShowByFoods which both take a parameter called cityAlias and then a second parameter which is featureAlias for the first and foodAlias for the second?

What about my post? ::) I really doubt it will ever work because how will an application know what rule to use when parsing url? Example:

mydomain.com/toronto-downtown-restaurants.htm

first part (toronto) is a city, but what about the second part? Is it a feature or food or area? In the rules all aliases have the same pattern (<someAlias:.*?>), which one to choose? Yii always chooses the first one (featureAlias).

What’s the big problem?

From the guide:


'post/<year:\d{4}>/<title>'=>'post/read',

http://www.yiiframework.com/doc/guide/1.1/en/topics.url#parameterizing-routes

Let me describe all those things.

Controllers and Actions




details/showByFoods

restaurants/showByArea



Routes




'<cityAlias:.*?>-<foodAlias:.*?>-restaurants/'=>'details/showByFoods',

'<cityAlias:.*?>-<areaAlias:.*?>-restaurants'=>'restaurants/showByArea',



Links


    

<?php echo CHtml::link('Sushi', array('details/showByFoods','cityAlias'=>'toronto', 'foodAlias'=>'Sushi'));?>

<?php echo CHtml::link('downtown', array('restaurants/showByArea','cityAlias'=>'toronto', 'areaAlias'=>'downtown'));?> 



I have the exactly scenario as describe here from this snario where the first route works and the second dont as a result its routing to the first route which is details/showByFoods

I hope you get the clear picture now and as our problem is the <cityAlias> which is identical for both and on same left position.

From this url


mydomain.com/toronto-downtown-restaurants.htm

passing parameters are two which are (cityAlias =‘toronto’ & areaAlias=‘downtown’)

I hope it’s now clear, could you please consider my last post scenario which are identical to my application task.

I really appreciate your time for solving this problem.

have a good day.

First of all: use createUrl:




<?php echo CHtml::link('downtown', $this->createUrl('restaurants/showByArea', array('cityAlias'=>'toronto', 'featureAlias'=>'downtown')));?>

<?php echo CHtml::link('Sushi', $this->createUrl('details/showByFoods', array('cityAlias'=>'toronto', 'foodAlias'=>'Sushi')));?>



Notice that the second createUrl uses the details controller.

Second of all:




 class DetailsController extends Controller {

 	public function actionShowByFoods($cityAlias, $foodAlias) {

    }

}


class RestaurantsController extends Controller {

 	public function actionShowByArea($cityAlias, $areaAlias) {

    }

}

jacmoe, it won’t work. I attached an example application so you can see. Also I added 3 more specific rules, so if you uncomment them, then everything will work as expected. It can be an easy solution of a problem.

P.S. Don’t forget to specify a path to the framework in index.php.

Andy, it works. ;)

Rules:





'urlManager'=>array(

    'showScriptName' => false,

    'urlFormat'=>'path',

    'rules'=>array(

        '<cityAlias>/<foodAlias>/restaurants'=>'details/showByFoods',

        '<cityAlias>/<areaAlias>/restaurants'=>'restaurants/showByArea',

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

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

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

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

    ),

),



Controllers:





class DetailsController extends Controller

{

	public function actionShowByFoods($cityAlias, $foodAlias)

	{

        echo "Details";

	}

}


class RestaurantsController extends Controller

{

	public function actionShowByArea($cityAlias, $areaAlias)

	{

        echo "Hello";

	}

}



Links:





<?php echo CHtml::link('downtown', $this->createUrl('restaurants/showByArea', array('cityAlias'=>'toronto', 'areaAlias'=>'downtown')));?>

<br/>

<?php echo CHtml::link('Sushi', $this->createUrl('details/showByFoods', array('cityAlias'=>'toronto', 'foodAlias'=>'Sushi')));?>



Tested in a fresh Yii app, as a matter of fact. :)

I didn’t download your app, so I won’t know what you did.

Gives me