Allowing only clean URLs in Yii - php

I have configured the CUrlManager in the config/main.php to use clean URL:
'urlManager' => array(
'showScriptName' => FALSE,
'urlFormat' => 'path',
'rules' => require(dirname(__FILE__) . '/routes.php'),
),
The clean URL function works perfectly, but I would like to prevent the default <controller>/<action> pattern match to occur.
This is my config/route.php:
<?php
return array(
'books' => 'book/index'
);
Now people can go to the same book page by 2 different URLs:
http://www.mysite.com/books
http://www.mysite.com/book/index
I want to disable the second URL pattern. Is this possible?

You can enable useStrictParsing in your url manager component.

Related

Yii create first test page

I am new to yii i have setup of sample yii demo application (default)n now i want to create new page but i am getting 404 error following are the steps i have followed.
1) In site Controller created new action
public function actionTest()
{
$this->render('test');
}
2) created new page in view folder test.php
echo "test";
3) In main.php (config file) added following code
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'caseSensitive' => false,
'rules' => array(
'test' => 'site/test',
),
),
4) when i run the application with URL
http://localhost/YiiTest/test
then got the error
The requested URL /YiiTest/test was not found on this server.
make sure you have rewrite your .htaccess file link

Yii routing - how to put that controller

I need to perform routing for the following url schemas:
website.com/some-category-name
website.com/some-category-name/entryName
some-category-name will be variable - some name of category
How to configure routing for this? I need to enter previous controllers, for example:
website.com/account
website.com/regiter
and want to everything that does not have controller name (so will be category name) going to controller Category.
I can't work it out.
use
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
'categoryName/<categoryName:\w+>' => array('site/category'),
'register' => array('site/register'),
'account' => array('site/account')
),
),
At first you must declare all rules for "non Category" actions, and after that dynamic rules (associated with category and antry):
'urlManager' => array(
'urlFormat' => 'path',
'showScriptName' => false,
'rules' => array(
// for example if your account and register actions in user controller
// ... you can write
'account' => 'user/account',
'register' => 'user/register',
// or with one rule
'<action(account|register)>' => 'user/<action>',
// and for all other 'static actions', such as login, logout ...
// after yhat you can declire dynamic rules
'<categoryName:\w+>' => 'category/index',
'<categoryName:\w+>/<entryName:\w+>' => 'category/entry'
),
),
So the code Yii::app()->createUrl('user/register') will generate url website.com/register, and accordingly the url website.com/register "goes to" register action of user controller (all other static rules like this way).
Now dynamic rules: code
Yii::app()->createUrl('category/index', array(
'categoryName' => 'first-category-name'
))
will generate url website.com/first-category-name, and vice versa: the url website.com/first-category-name "goes to" category/index action and in it will be available $_GET['categoryName'] parameter, which will be equal to "second-category-name"․
Accordingly code
Yii::app()->createUrl('category/index', array(
'categoryName' => 'some-category-name',
'entryName' => 'some-entry-name'
))
will generate url website.com/some-category-name/some-entry-name, and in category/entry action you can get $_GET['categoryName'] equal to "some-category-name" and $_GET['entryName'] equal to some-entry-name.
I hope this help you to understand how works rules in Yii.
Thanks!

YII friendly SEO url

I am struggling with this problem and not found any suitable answer.
I want my_site/user/1 to become my_site/user/user_name
My urlManager looks like this:
'urlManager' => array(
'urlFormat' => 'path',
'rules' => array(
'user/<username:\w+>'=>'user/view',
'<controller:\w+>/<id:\d+>'=>'<controller>/view',
'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',
'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',
),
'showScriptName' => false,
),
User Controller:
public function actionView($username)
{
$this->render('view', array(
'model' => $this->loadModel($username),
));
}
When i hit /user/admin it redirects me to actionView not to the actionAdmin from my controller and i have multiple such actions like create, delete and so on.
How can i avoid this? Is there an alternative?
Thanks.
The urlManager try's to match the url to a controller and action.
the 1st part of
'user/<username:\w+>'=>'user/view',
has matched to the user controller and the next part it looking for any string that consists of words, then sent the user to user/view
I recommend changing user/<username> to manage-user/<username> or my-account/<username>, something like that.

Yii, controllers in different subfolders

I have folder hierarchy
---protected
------...
------controller
---------admin
------------OneController.php
------------TwoController.php
---------user
------------ThreeController.php
------------FourController.php
also i add them in main.php as
'import' => array(
'application.models.*',
'application.forms.*',
'application.components.*',
'application.fetcher.*',
'application.controllers.admin.*',
'application.controllers.user.*', ...
add route for admin
'urlManager' => array(
'showScriptName' => false,
'urlFormat' => 'path',
'rules' => array(
// ...
'admin' => 'admin/one/index',
but this doesn't work, can you help to deal with it? I want do simply routes to subfoldered controllers.
I think your syntax of rule is wrong. Try to use
'rules' => array(
'admin' => 'admin/one/index'
)
I Found solution. My mistake was on controller, I have default (old) OneController in /protected/controllers that's why routes give me 'old' data, when I change name of (old) OneController, trouble gone. And after that route give me new one from /protected/controllers/admin/OneController.
it was like this one
---protected
------...
------controller
---------OneController.php <-- this gives wrong data even error because of routes
---------admin
------------OneController.php
------------TwoController.php
---------user
------------ThreeController.php
------------FourController.php

Zend Framework 2 - Why i can't override MvcEvent's MatchRoute?

i would like to match all requests where user is unlogged to controller Admin\Controller\Sign and action in. I wrote this code in onBootstrap() method in Module.php file :
if (!$authService->hasIdentity()) {
$routeMatch = new RouteMatch(
array(
'controller' => 'Admin\Controller\Sign',
'action' => 'in'
)
);
$event->setRouteMatch($routeMatch);
}
I don't get any errors, but code doesn't work, why?
The problem here is that the application route event (MvcEvent::EVENT_ROUTE) is triggered after the (MvcEvent::EVENT_BOOTSTRAP).
Which means even if you're setting the route match at the bootstrap level, the application is going to override it with the route match of the request after the MvcEvent::EVENT_ROUTE.
If you want to avoid this overriding you need to add a listener for the route event with a very low priority to make sure it will not be overridden:
$e->getApplication()->getEventManager()->attach(MvcEvent::EVENT_ROUTE, array($this, 'onRouteEvent'), -1000000);
Note : the onRouteEvent would be the method of your Module class that handles the route event (similar to your code).
If you want to short-circuit your application running at the bootstrap level, what you can do is to send the headers with redirection code to the client:
//get the url of the login page (assuming it has route name 'login')
$url = $e->getRouter()->assemble(array(), array('name' => 'login'));
$response=$e->getResponse();
$response->getHeaders()->addHeaderLine('Location', $url);
$response->setStatusCode(302);
$response->sendHeaders();
add a route entry sign_in as below in the routes section of the module.config.php under admin module
'sign_in' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin/sign/in',
'defaults' => array(
'controller' => 'sign',
'action' => 'in',
),
),
),
and call the route in the controller like this
$this->redirect()->toRoute('sign_in');

Categories