Yii routes and creation of URLs with multiple parameters - php

I would like to get the URL as follow:
http://domain.com/post/1/some-titles-here
But I'm getting:
http://domain.com/post/1?title=some-titles-here
I am using this config:
'urlFormat' => 'path',
...
//'post/<id:\d+>/<title>' => 'post/view/',
'post/<id:\d+>/<title:\w+>' => 'post/view/',
'post/<id:\d+>' => 'post/view/',
...
Then to get the URL I am executing:
Yii::app()->createAbsoluteUrl('post/view', array('id' => $this->id,'title' => $this->title));
im following the third rule here:
http://www.yiiframework.com/doc/guide/1.1/en/topics.url#using-named-parameters

The regular expression you're using to match the title is incorrect: <title:\w+> will only match single words but your title has hyphens as well.
Tuan is correct; it's matching the next rule. That's because the URL manager works its way down the rules until it finds one that matches.
Use this rule instead:
'post/<id:\d+>/<title:([A-Za-z0-9-]+)>' => 'post/view/',
That will match titles with letters, numbers, and hyphens.

This is a code that work for me:
'urlManager'=>array(
'urlFormat'=>'path',
'showScriptName' => false,
'rules'=>array(
'' => 'site/index',
'article/<id:\d+>/<alias:[-\w]+>' => 'article/view',
'article/cat/<id:\d+>-<alias:[-\w]+>' => 'category/view',
Result urls:
http://wowjp.black.dragon/article/2/test-zagolovka
http://wowjp.black.dragon/article/cat/3-345435

Related

Is there a way to convert "+" to "-" in URL Yii2?

I am trying to change the paramlinks to include the name of a post in my yii2 application.
example.com/item/hello+world
to
example.com/item/hello-world
These are the rules of in my urlmanager in frontend/config/main.php
'urlManager' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
'/' => 'site/index',
'item/<title:[A-Za-z0-9 -_.]+>' => 'item/view',
],
]
$hi = 'example.com/item/hello+world';
$hi = str_replace('+', '-', $hi);
echo $hi;
like this you can replace what you need replacing with str_replace
output:
example.com/item/hello-world
The output url you displayed is put in a variable, then i fill in what I want replaced +, what should overwrite it is the - sign and then store it again in a variable called $hi again.
Your problem is the Url::toRoute method. By default, it will replace empty spaces by a "+". And there is no configuration to change that (at least I did not find).
You could use a str_replace like #baboizk mentioned, or, if you want to cover any accents, symbols, etc. You can use BaseInflector::slug. Example:
Url::toRoute(['item/view', 'title' => BaseInflector::slug($model->title)]);
But i'm still not sure how your actionItem works, because it probably needs to search the model by it's title and you are changing it.

YII urlManager rewrite singe URL with multiple parameters

Ok, removed my previous question and reformulated the new one, otherwise no one would understand, sorry. So here the problem that's left:
So I want to rewrite an URL to a single word which works with zero, one and two parameters, but not with 3:
Original url with 2 paramaters:
index.php?r=site/page&view=exposities&tijd=nu
urlmanager rule:
'exposities_nu'=>array('site/page', 'defaultParams' => array('view' => 'exposities', 'tijd'=>'nu')),
result:
/exposities_nu/
Now what doesn't work:
Original url with 3 parameters:
index.php?r=site/page&view=exposities&tijd=vestiging&locatie=1
urlmanager rule:
'knsm'=>array('site/page', 'defaultParams' => array('view' => 'exposities', 'tijd'=>'nu', 'locatie'=>'1')),
result:
index.php?r=site/page&view=exposities&tijd=vestiging&locatie=1
Does anyone why this last url isn't shortened to /knsm/?
Maybe you didn't set the url in the URL Manager right. See this example:
return array(
......
'components'=>array(
......
'urlManager'=>array(
'urlFormat'=>'path',
'rules'=>array(
'post/<id:\d+>/<title:.*?>'=>'post/view',
'posts/<tag:.*?>'=>'post/index',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
),
),
);
Also you have to create you URLs correct:
Yii::app()->createUrl('post/view', array(
'id'=>$this->id,
'title'=>$this->title,
));

URL Manager - action parameter optional and link creation

I have below URL mapping in my main.php file . You can see I am expecting parameter id as an optional
'urlManager'=>array(
'urlFormat'=>'path',
'showScriptName'=>false,
'urlSuffix' => '/',
'useStrictParsing' => true,
'rules'=>array(
'' => 'site/index',
'<action:(signIn|signUp|logout)>' => 'site/<action>',
'<controller:\w+>(/<id:\d+>)?'=>'<controller>/index',
'<controller:\w+>/<action:\w+>(/<id:\d+>)?'=>'<controller>/<action>',
),
),
with the above rules If I create a link using below code
<?php echo CHtml::link('×', array('index', 'id' => $this->group_id), array('class' => 'linkclose')); ?>
this creates link some thing like below , which is wrong
http://localhost/blog(/872280)?/
It should generate some thing like below
http://localhost/blog/872280/
If I don't pass the parameter in the link I mean
<?php echo CHtml::link('×', array('index'), array('class' => 'linkclose')); ?>
this generates
http://localhost/blog/index
which is fine .
But with the parameter passing it is messing up the link .. Could some one help me on this ? Thanks
URL rules in their entirety are not regular expressions. Thus, optional groups like (...)? aren't honored. You can work around this by specifying alternative rules:
'rules'=>array(
...
'<controller:\w+>/<id:\d+>'=>'<controller>/index',
'<controller:\w+>'=>'<controller>/index',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),

Zend route regex, optional parameters

I need some help about my routes in Zend (Zend1) ...
I need that I can use my route like that :
http://mywebsite.com/myfolder/region/job/
http://mywebsite.com/myfolder/region/job/add
http://mywebsite.com/myfolder/region/job/add/page
http://mywebsite.com/myfolder/region/job/page
Parameters add and page are optional ...
This is what I did
$route = new Zend_Controller_Router_Route_Regex(
'myfolder/([^/]+)/([^/]+)/?([^/]+)?/?([0-9]+)?',
array('controller' => 'myfolder','action' => 'search'),
array(1 => 'region',2 => 'job', 3 => 'add', 4 => 'page'),
'myfolder/%s/%s/%s/%s'
);
Obviously, it doesn't work ...
What I want? I want that last the two parameters (add and page) are optional ...
Can you help me? what's wrong with my regex?
EDIT 1:
Ok, so I tried it, but isn't ok ...
I need that parameters add and page are optional ...
$route = new Zend_Controller_Router_Route(
'myfolder/:region/:job/:add/:page',
array(
'controller' => 'myfolder',
'action' => 'search',
'region' => 'XX',
'job' => '',
'add' => '',
'page' => 1
),
array(
'region' => '[a-zA-Z-_0-9-]+',
'job' => '[a-zA-Z-_0-9-]+',
'add' => '[a-zA-Z-_]+',
'page' => '\d+'
)
);
With that, this one http://mywebsite.com/myfolder/region/job/page doesn't work ...
EDIT 2:
I also tried with 'myfolder/:region/:job/*', but the result is same, doesn't work as I want ...
I really wonder if it is possible ...
EDIT 3:##
$route = new Zend_Controller_Router_Route_Regex('myfolder/([^/]+)/([^/]+)(?:/|$)(?:(?!\d+(?:/|$))([^/]+)(?:/|$))?(?:(\d+)(?:/|$))?$',
array('controller' => 'myfolder', 'action' => 'recherche', 'presta' => ''),
array(1 => 'region',2 => 'job', 3 => 'presta', 4 => 'page'),
'myfolder/%s/%s/%s/%s');
Prepare yourself.
The RegEx
myfolder/([^/]+)/([^/]+)(?:/|$)(?:(?!\d+(?:/|$))([^/]+)(?:/|$))?(?:(\d+)(?:/|$))?$
See it working on RegExr (on RegExr, I had to add \n\r to one of the negated classes so it didn't match all my line breaks, in practice you probably won't be dealing with line breaks though.)
The important thing to note on RegExr is that in the 4th case, the page number is in the 4th capture group, with nothing in the 3rd group.
Explanation
myfolder/([^/]+)/([^/]+) All looking good up to here, no changes yet.
(?:/|$) Match a / or end of input.
Next, overall we have a non-capturing group that is optional. This would be the add section.
(?:(?!\d+(?:\|$))([^/]+)(?:/|$))?
Now lets break it down further:
(?!\d+(?:/|$)) Make sure its not a page number - digits only followed by / or end of input. (Negative lookahead)
([^/]+) Our capture group - add in the example.
(?:/|$) Match a / or end of input.
Now for our page number group, again it's optional and non-capturing:
(?:(\d+)(?:/|$))? Captures the numbers, then matches / or end of input again.
$ And just in case it tries to match substrings of actual matches, I threw in another end of input anchor (since you can match as many in a row as you like), although the regex functions without it.
Generating The Path
What you basically want is a way of doing this:
At the moment the 2nd and 3rd parameters are:
array(1 => 'region',2 => 'job', 3 => 'add', 4 => 'page'),
'myfolder/%s/%s/%s/%s'
You want them to be something like:
array(1 => 'region',2 => 'job', 3 => '/'+'add', 4 => '/'+'page'),
'myfolder/%s/%s%s%s'
Where you only add the / if the optional group is present. The code above won't work but perhaps there is some way you could implement that.

Zend pagination and routing

Having a bit of trouble getting my URLs to work properly.
The URL looks like this: /messages/from/1/page/5
My route looks like this
$router->addRoute('messages-from',
new Zend_Controller_Router_Route('messages/from/:user_id/:page', array(
'controller' => 'messages',
'action' => 'from',
'page' => 1
))
);
Which works fine. But the URL is missing the /page/ part. If I add it in:
'messages/from/:user_id/page/:page'
then it breaks and the user_id param is always null.
How can I fix this?
Thanks!
Since you want to be able to leave off the /page/ part from the URL, you would have to define two separate routes, one that matches the user ID and page parameters and one that only matches the user ID without the page so the router can find route matches in both cases.
Alternatively, this regex based route works in both cases.
$route = new Zend_Controller_Router_Route_Regex(
'messages/from/(\d+)(?:/page/(\d+)/?)?',
array(
'controller' => 'messages',
'action' => 'from',
'page' => 1,
),
array(
1 => 'from',
2 => 'page',
)
);
$router->addRoute('messages-from', $route);
Based on the URL you supplied, I assumed in the regex that the from parameter is an integer. If you can have strings passed, you will need to change the (\d+) pattern to something more suitable like ([\w\d_-\.]+).

Categories