I have a child class that parses urls customly that extends CBaseUrlRule.
The parseUrl() function must return a string that is 'controller/action', yet what I want to do is to be able to pass named parameters to that action. Is this possible?
For example, a url might be:
catalogName/brand/brandName/product/productname/
What I want is to redirect that path to the Catalog's index action, with that action having:
public function actionIndex($catalogName, $brandName, $productName) {
//do smthng
}
I'd make a simple url rule, but then I need the class to process certain information before parsing the url.
You can use Named Parameter by defing rules in main.php, like :
array(
'components' => array(
......
'urlManager' => array(
'urlFormat' => 'path',
'rules' => array(
'<catalogName>/brand/<brandName>/product/<productname>/' => 'catalog/index',
),
),
),
);
Related
I have the ability for users to define URLs for some of their items so, for example:
http://x.com/mynewobject
mynewobject would be defined by the user in a form and I need to be able to say in the UrlManager to math that, but also match everything else.
Problem is the default rules in the UrlManager will try and catch the mynewobject controller and throw a 404 when it cannot.
What is the way to make a UrlManager catch user defined URLs?
The best way I have found of doing this, without manually declaring your URLs, is to actually take a closer look at the Yii 2 documentation.
It actually shows a good example here of user generated URLs http://www.yiiframework.com/doc-2.0/guide-runtime-routing.html#creating-rules which I used to complete my task.
The configuration I used was:
'urlManagerFrontend' => [
'class' => 'yii\web\UrlManager',
'enablePrettyUrl' => true,
'showScriptName' => false,
'cache' => null,
'baseUrl' => '/',
'rules' => [
[
'class' => 'common\components\ObjectUrlRule',
'pattern' => '<slug:.*>',
'route' => 'site/index'
],
'<controller:[\w-]+>/<id:\d+>'=>'<controller>/view',
'<controller:[\w-]+>/<action:[\w-]+>/<id:\d+>'=>'<controller>/<action>',
'<controller:[\w-]+>/<action:[\w-]+>'=>'<controller>/<action>',
// your rules go here
]
],
And a rule class of:
<?php
namespace common\components;
use Yii;
use yii\web\UrlRule;
use common\models\ObjectUrl;
class ObjectUrlRule extends UrlRule
{
public function parseRequest($manager, $request)
{
$pathInfo = trim($request->getPathInfo());
if(!$pathInfo){
return false;
}
$controller = Yii::$app->createController($pathInfo);
if($controller){
return false;
}
$objectUrl = ObjectUrl::find()->where(['url' => $pathInfo])->one();
if(!$objectUrl){
return false;
}
return $objectUrl->getUrl($pathInfo);
}
}
Where ObjectUrl is the model (table) which contains the map of user generated URLs.
The good thing about this class, as well, is that it will not run the database call unless the controller does not exist and there is a pathinfo.
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!
I have been trying to configure our Module.php to use the Module Manager Listeners for configuration (i.e interfaces that are available under Zend\ModuleManager\Feature\*). Specifically, I want to be able to configure the routes of my module outside of the main module.config.php. I have not been able to find any actual examples of this.
What I have found, if I have read the documentation correctly, is that the method getRouteConfig() should merge in my routes into the array provided by getConfig()?
Module.php
class Module implements Feature\RouteProviderInterface
{
//...
public function getRouteConfig()
{
return include __DIR__ . '/config/route.config.php';
}
//...
}
/config/route.config.php
return array(
'route_manager' => array(
'router' => array (
'routes' => array(
//.. routes that were working correctly when added to module.config.php
),
),
),
);
I can see the array returned via getRouteConfig() so I know the method is being called correctly.
Perhaps I am misunderstanding the purpose of the above interface, or I have not provided the correct "key" (route_manager) for this to be merged correctly, as I'm getting 404 for my routes.
Any help would be appreciated!
I haven't done this in the way you mentioned yet, but the key route_manager is not required within the getRouteConfig() Method.
This is due to the fact that all of the get{$specificManager}Config()-Methods are called directly from their respective Manager-Classes. Therefore the initial key is not required. Using another terminology, when using getRouteConfig() you are already in the scope of route_manager. Same as when you use getServiceConfig() you're already in the scope of service_manager. However getConfig() is within the application-scope and therefore accessing configuration of application-parts, you need to address tose specificaly.
One thing to note is: the configuration of getConfig() can be cached to increase performance, whereas all the other get{$specificManager}Config() methods are not. Especially in the case of the RouteConfiguration I'd highly suggest to use the getConfig()-Method for your RouteConfig.
If you really need to separate the configuration, then I'd suggest the way that #Hendriq displayed for you.
Well I have it working but I only use the getConfig(). What is do is I use an array_merge in the getConfig().
public function getConfig()
{
return array_merge(
require_once 'path_to_config/module.config.php',
require_once 'path_to_config/routes.config.php'
);
}
My router.config.php looks then like:
return [
'router' => [
'routes' => [
// routes
]
]
];
This way I also got some other config files seperated (ACL).
Edit
Thanks to the article Understanding ZF2-Configuration, I got an idea. I think your array should not be:
return array(
'route_manager' => array(
'router' => array (
'routes' => array(
//.. routes that were working correctly when added to module.config.php
)
)
)
);
but rather be
return array(
'router' => array (
'routes' => array(
//.. routes that were working correctly when added to module.config.php
),
),
);
The getRouteConfig is similar to the other providers it is there so you're able to create some custom routes. I guess what you're trying to do is most appropiate through hendriq's method.
An example of getRouteConfigcan be found at http://zf2cheatsheet.com/
public function getRouteConfig()
{
return array(
'factories' => array(
'pageRoute' => function ($routePluginManager) {
$locator = $routePluginManager->getServiceLocator();
$params = array('defaults' => array('controller' => 'routeTest','action' => 'page','id' => 'pages'));
$route = Route\PageRoute::factory($params);
$route->setServiceManager($locator);
return $route;
},
),
);
}
In our Module\Route namespace we create the class PageRoute which implements Zend\Mvc\Http\RouteInterface and, in our specific case for the example, Zend\ServiceManager\ServiceManagerAwareInterface. Now just implement the functions of the interface... In the sample he uses Doctrine to load the pages from the database.
Finally we can add our new custom route to our module.config.php so it can be used:
'page' => array(
'type' => 'pageRoute',
),
As you can see in this last step we go back to Hendriq's solution as the intended use is not to load the routes into the router, but creating custom routes.
Hope this helps
Hello (sorry for my english...)
I got an aplication in Yii. I choose diffrent databases depending on $_GET['project']. My urls looks like index.php?r=controler/action&project=MyProject.
But i have to add &project=.. to every single link on my site, how can i make Yii do it automatically?
If you are using CUrlManager::createUrl() (or one of the other createUrl() variants) to create your links, you could override it in your own custom UrlManager:
class UrlManager extends CUrlManager {
public function createUrl($route, $params=array(), $ampersand='&') {
isset($params['project']) || $params['project'] = 'MyProject';
return parent::createUrl($route, $params, $ampersand);
}
}
Then in your config be sure to use your own custom UrlManager class:
return array(
...
'components' => array(
'urlManager' => array(
'class' => 'UrlManager',
),
),
...
);
I have one route that looks like this:
Router::connect('/Album/:slug/:id',array('controller' => 'albums', 'action' => 'photo'),array('pass' => array('slug','id'),'id' => '[0-9]+'));
and another like this:
Router::connect('/Album/:slug/*',array('controller' => 'albums','action' => 'contents'),array('pass' => array('slug')));
for what doesn't match the first. In the 'contents' action of the 'albums' controller, I take care of pagination myself - meaning I retrieve the named parameter 'page'.
A URL for the second route would look like this:
http://somesite.com/Album/foo-bar/page:2
The Above URL indeed works, but when I try to use the HTML Helper (url,link) to output a url like this, it appends the controller and action to the beginning, like this:
http://somesite.com/albums/contents/Album/foo-bar/page:2
Which i don't like.
The code that uses the HtmlHelper is as such:
$html->url(array('/Album/' . $album['Album']['slug'] . '/page:' . $next))
See below url it is very help full to you
http://book.cakephp.org/2.0/en/development/routing.html
Or read it
Passing parameters to action
When connecting routes using Route elements you may want to have routed elements be passed arguments instead. By using the 3rd argument of Router::connect() you can define which route elements should also be made available as passed arguments:
<?php
// SomeController.php
public function view($articleId = null, $slug = null) {
// some code here...
}
// routes.php
Router::connect(
'/blog/:id-:slug', // E.g. /blog/3-CakePHP_Rocks
array('controller' => 'blog', 'action' => 'view'),
array(
// order matters since this will simply map ":id" to $articleId in your action
'pass' => array('id', 'slug'),
'id' => '[0-9]+'
)
);
And now, thanks to the reverse routing capabilities, you can pass in the url array like below and Cake will know how to form the URL as defined in the routes:
// view.ctp
// this will return a link to /blog/3-CakePHP_Rocks
<?php
echo $this->Html->link('CakePHP Rocks', array(
'controller' => 'blog',
'action' => 'view',
'id' => 3,
'slug' => 'CakePHP_Rocks'
));