Yii2 pretty URL: automatically convert everything with slashes (including all parameters) - php

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.

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.

Related

How to make right url address in Yii2

I need to do an url address that looks like website/user/username where username is coming from database. I've tried to reach it by placing a $user variable in my action function as a parameter and result looks like this website/action?user=username. But it looks kind of hinty and ugly. How can I get a desirable result?
First you need to configure url rules in config/web.php.
[
'components' => [
'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'enableStrictParsing' => false,
'rules' => [
"user/<username:\w+>"=> "controller/action"
],
],
],
]
And add url match condition in rules array like
"user/<username:\w+>"=> "controller/action"
Create. htaccess file with below url condition in web folder
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
And generate urls with Url helper class or Html class like below
echo Url::to(['controller/action', 'username' => 'jack']);
Or
echo Html::a('Profile', ['controller/action', 'username' => 'jack'], ['class' => 'profile-link'])
Note:- controller name, action name and username should match with Url condition. Which we define in rules array.

Yii2 does not find action

'urlManager' => [
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<controller:\w+>/<id:\d+>/<action:\w+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
],
],
Not it is clear why references of a /controller/name-action/id/1 do work, /controller/1/name-action do not work, and without hyphen everything works, according to documentation of action name-action it is actionNameAction??
public function actionNameAction($id) {
// some code
}
Inline Actions
In advance all thanks.
\w does not include -.
Change pattern to [\w\-]+.
I think you are confused with zend framework and Yii2.In yii2 it is actionActionName.While using it in url's the capitals are changed to lower case with a hyphen preceding them.
For example,
if the controller is Orders
and the action is OrderAnalysis
then the url would be something like orders/order-analysis.
Moreover any id or any other parameter is added only after routing the app to its correct controller action.
Also now coming to your problem I think i found a backdoor to it-
// creates an anchored URL: /index.php?r=post%2Fview&id=100#content --------------------------
echo Url::to(['post/view', 'id' => 100, '#' => 'content']);

Yii2 url manager don't parse urls with get parameter

I've created a module named catalogue with, for the moment, two actions in the default controller:
actionIndex
actionLineProducts
in the index view I have some link which run the line-product's action, the url was the result of:
Url::to(['line-products', 'line' => $line->name])
my goal is to obtain a link like
catalogue/{line-name}
where line-name is the parameter I send to action LineProducts.
My urlManager configurations are:
'enablePrettyUrl' => true,
'showScriptName' => false,
'rules' => [
'<moduls:catalogue>/<controller:default>/<action:line-products>/<line:*>' => '<module>/<line>',
'<controller:\w+>/<id:\d+>' => '<controller>/view/',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
],
.htaccess configurations:
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
Can anyone explain me why my URL is always like:
http://my-site.dev/catalogue/default/line-products?line={line-name}
You swapped the configuration. The key is the pattern of the url as passed from the browser. The value is the route. Since you are using a specific module, controller and action you can pass those in directly:
'rules' => [
'catalogue/<line>' => 'catalogue/default/line-products'
...
]
You can read the Routing and Url Creation page in the Yii2 guide for more information.

Htaccess URL rewrite to Yii2 application

I have the following url structures in my Yii2 application
http://127.0.0.1/frontend/web/index.php?r=site%2Flogin
http://127.0.0.1/frontend/web/index.php?r=site%2Fpage2
http://127.0.0.1/frontend/web/index.php?r=site%2Fsample
http://127.0.0.1/frontend/web/index.php?r=site%2Fsignup
How can I convert that URL to something like
http://127.0.0.1/login.php
http://127.0.0.1/page2.php
http://127.0.0.1/sample.php
http://127.0.0.1/signup.php
I should remove frontend/web/index.php?r=site%2F
I tried like and it didn't work
Options -Multiviews
RewriteEngine On
RewriteBase /
# Force search engines to use http://127.0.0.1/frontend/web/
RewriteCond %{HTTP_HOST} !^http://127\.0\.0\.1/frontend/web/$
RewriteRule ^(.*) http://127.0.0.1/frontend/web/$1 [R=301,L]
# Specify search friendly URLs
RewriteRule ^login\.php$ /index.php?r=site%2Flogin [L]
I also tried like and it didn't work too.
RewriteEngine on
RewriteRule ^frontend/web/index.php?r=site%2F([^\./]+) /$1.php [L]
No need to change .htaccess to achieve this. Adjust urlManager component.
Add this to your application config:
'components' => [
'urlManager' => [
'enablePrettyUrl' => true, // Cancel passing route in get 'r' paramater
'showScriptName' => false, // Remove index.php from url
'suffix' => '.php', // Add suffix to all routes (globally)
],
// Compare requested urls to routes
'rules' => [
'login' => 'site/login',
'page2' => 'site/page2',
'sample' => 'site/sample',
'signup' => 'site/signup',
],
],
As for removing controller part from all other routes - it violates key MVC concepts.
How you define to which controller requested action belongs in that case?
And what in case of actions with the same name?
For example: http://127.0.0.1/create.php - should it load site/create or users/create?
Also I don't sure if it's good practice, but you can write comparisons to all routes the same way with rules, but all action names should be unique.
Conclusion: you can modify urls to desired view as I mentioned above, but omitting controller names is only recommended for default controller (SiteController).
Official documentation:
UrlManager
$enablePrettyUrl
$showScriptName
$suffix
$rules
Routing and URL Creation

Yii url management issue

I'm developing a web application using Yii Framework and I'm having a little problem with url rewriting.
The issue is with the last rule in the code below. It was supposed to turn localhost/app/category/some-friendly-url-category-name (this part would appear in the browser) into localhost/app/category/view/id/some-friendly-url-category-name
It works fine when the category name is only one word, like: vehicles.
But it doesn't work when it has more than a word, like: children-stuff
'urlManager'=>array(
'showScriptName' => false,
'urlFormat'=>'path',
'rules'=>array(
'<controller:\w+>/<id:\d+>' => '<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>' => '<controller>/<action>',
'<controller:\w+>/<action:\w+>' => '<controller>/<action>',
'category/<id:[A-Za-z0-9_\-]+>' => 'category/view',
),
),
You don't need to escape the hyphen in the ID:
'category/<id:[A-Z a-z 0-9 _ -]+>' => 'category/view',
A simpler solution would be:
'category/<id>' => 'category/view',
Also, do note that you have to place this specific rule above the general (default) rules.
Move the category rule above the <controller> ones. Otherwise, your app would try to find a actionChildrenStuff() in your CategoryController, for example.
Usually I would add new rules above those three general ones.

Categories