8

I'm working with Yii2 and I would like to use urlManager with routing to convert all non-letter and non-number characters into slashes. I have looked at a lot of question what have already been asked (#1, #2, #3, #4) but none solved it since they either show a little similar but not what I want or not working for me at all.

I have simple urlManager rules:

//...
'urlManager' => [
    'class' => 'yii\web\UrlManager',
    'enablePrettyUrl' => true,
    'showScriptName' => false,
    'rules' => array(
        '<controller:\w+>/<id:\d+>' => '<controller>/view',
        '<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
        '<controller:\w+>/<action:\w+>' => '<controller>/<action>',
    ),
],

.htaccess (also simple):

RewriteEngine on
# If a directory or a file exists, use it directly
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
# Otherwise forward it to index.php
RewriteRule . index.php

In my case, my ugly URL is this (SiteController -> public function actionTestRouter()):

localhost/frontend/web/index.php?r=site%2Ftest-router&ident=10&token=ADB&module=P120

With rules I have written above, I get better result (because it removes index.php?r= and converts %2F to /):

localhost/frontend/web/site/test-router?ident=10&token=ADB&module=P120

What I want to get:

localhost/frontend/web/site/test-router/ident/10/token/ADB/module/P120

My several attemps with rules were:

'test-route/<ident:\d+>/<token:\w+>/<module:\w+>' => 'test-route' // 1
'<controller:\w+>/<action:\w+>/<ident:\d+>/<token:\w+>/<module:\w+>' => '<controller>/<action>' // 2
'<controller:\w+>/<action:\w+>/<slug:[a-zA-Z0-9_-]+>/' => '<controller>/<action>/<slug>' // 3 (not even sure what slug does here

It would also be super nice if the rules would apply to any parameters and values, regardless of their name and values.

Community
  • 1
  • 1
Gynteniuxas
  • 7,035
  • 18
  • 38
  • 54
  • Thanks much for your Q. This is what has Yii 1 has by default as a urlManager setting urlFormat='Path', Yii 2 was a step back in this aspect, I don't see anything wrong with it, and I spent much time already with figuring it out. Yii 1 logic for is directly in class `CUrlManager -> parsePathInfo ($pathInfo)` method. So in Yii 2, we have to overcome by own implementation or reuse somehow from Yii1 – FantomX1 Aug 26 '19 at 19:04
  • Intersting related question, but for Yii 1 , though maybe the same way with wildcard repeat/multiply operator can be accomplished the same similarly - https://stackoverflow.com/a/20429218/3419535 , or a similar usage yii 2 cookbook but only for multiplied values of a single parameter - https://github.com/samdark/yii2-cookbook/blob/master/book/urls-variable-number-of-parameters.md – FantomX1 Aug 26 '19 at 19:14

1 Answers1

7

Your second attempt

'<controller:[\w\-]+>/<action:[\w\-]+>/<ident:\d+>/<token:\w+>/<module:\w+>' => '<controller>/<action>' // 2

will take/create urls

localhost/frontend/web/site/test-router/10/ADB/P120

without names of params in url and these params will be used only in this order and their list is fixed as you see

If you want add their names in url (for estetic or seo purposes like in your question):

'<controller:[\w\-]+>/<action:[\w\-]+>/ident/<ident:\d+>/token/<token:\w+>/module/<module:\w+>' => '<controller>/<action>',  // 2

And url creation for these routes will be same:

echo Url::to(['site/test-router', 'ident' => 100, 'module' => 100, 'token' => 100]);

If you want parse various length of this list of params, you can use smth like this:

'<controller:[\w\-]+>/<action:[\w\-]+>/<params:[a-zA-Z0-9_\-\/]+>' => '<controller>/<action>'

or specify it only for one route:

'site/test-route/<params:[a-zA-Z0-9_\-\/]+>' => 'site/test-route'

So in action you will get parameter params: Yii::$app->request->get('params'); parse it with regexp.

user1852788
  • 4,278
  • 26
  • 25
  • Thanks for the answer. But I got this error: `preg_match(): Compilation failed: range out of order in character class at offset 66` when trying the last or second-last options. :/ – Gynteniuxas Jun 30 '16 at 11:46
  • Ah since 5.2 minus should be also escaped. Answer edited. – user1852788 Jun 30 '16 at 13:14
  • I still don't get it right. :/ I tried your edit and entered `localhost/frontend/web/site/test-router/ident/10/token/ADB/module/P120` (directly into URL) but I get `404` error. – Gynteniuxas Jun 30 '16 at 13:38
  • Its because your action in route contains minus `test-route`. so instead mask `` you should use mask ``. Answer edited. – user1852788 Jun 30 '16 at 13:51
  • I see. Thanks, I'll try tomorrow. :) – Gynteniuxas Jun 30 '16 at 19:02
  • Well, that still didn't work. I get the same result, regardless of which option I use. I think I'm missing something, not just in rules. – Gynteniuxas Jul 01 '16 at 05:49
  • looks like you type wrong url in browser. your url should be smth like: `http://localhost/site/test-route/ident/10/token/ADB/module/P120` – user1852788 Jul 01 '16 at 08:42
  • Check right url format by `echo Url::to(['site/test-route', 'ident' => 100, 'module' => 100, 'token' => 100]);` for 1,2 variants of urlManager rule and `echo Url::to(['site/test-route', 'params' => 'zxcasd']);` for 3,4 variants. – user1852788 Jul 01 '16 at 09:06
  • I think I'm closer. I get like I wanted (for example, `test-route/20/PDAS/P12`) with `echo Html::to()`, but if I try `Html::a('ok', ['site/test-route', 'ident' => 20, 'token' => 'PDAS', 'modul' => 'P12']`, I get 404 again. – Gynteniuxas Jul 01 '16 at 13:30
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/116205/discussion-between-user1852788-and-edvin-tenovim). – user1852788 Jul 01 '16 at 14:08