I use two modules in my zend framework 2 application:
Module A
Module B
I encounter the problem that I can only use one of the routes that I have configured for the corresponding module. The route that is used, depends on the sorting of the modules in the application.config.php file:
<?php
return array(
'modules' => array(
'ModuleA','ModuleB'
);
?>
Every module contains nearly the same configuration module.config.php:
<?php
return array(
'router' => array(
'routes' => array(
'ModuleA' => array(
'type' => 'Literal',
'options' => array(
'route' => '/moduleA',
'defaults' => array(
'__NAMESPACE__' => 'ModuleA\Controller',
'controller' => 'index',
'action' => 'index',
),
),
'may_terminate' => false,
'child_routes' => array(
'moduleA-index' => array(
'type' => 'Segment',
'options' => array(
'route' => '/index[/:action]',
'defaults' => array(
'controller' => 'index',
'action' => 'index'
)
)
)
)
)
)
)
);
Current situation:
URL /moduleA routes to /ModuleA/Index/Index
URL /moduleB routes to /ModuleA/Index/Index
Expected:
URL /moduleA routes to /ModuleA/Index/Index
URL /moduleB routes to /ModuleB/Index/Index
Do you have any advice for me how to use both configurations/routes in the right way?
Are you using 'controller' => 'index', in your moduleB config too?
if yes then there is your problem index is on alias and only 1 controller can have that alias, in other words alias's should be unique throw out the Application and not just a module.
define a unique name(alias) for your controller and you will be fine.
in my project i just use the FQN so there is no confusion (Namespace\Controller\ControllerName)
Just add 'priority' param
<?php
return array(
'router' => array(
'routes' => array(
'ModuleA' => array(
'type' => 'Literal',
'priority' => 100, // <-- priority
'options' => array(
'route' => '/moduleA',
'defaults' => array(
'__NAMESPACE__' => 'ModuleA\Controller',
'controller' => 'index',
'action' => 'index',
),
),
'may_terminate' => false,
'child_routes' => array(
'moduleA-index' => array(
'type' => 'Segment',
'options' => array(
'route' => '/index[/:action]',
'defaults' => array(
'controller' => 'index',
'action' => 'index'
)
)
)
)
)
)
)
);
Related
I'm using this config as my application module config in Zend2 which is really normal and every one suggested as a standard routing rule:
'controllers' => array(
'invokables' => array(
'Application\Controller\Index' => 'Application\Controller\IndexController',
),
),
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
'application' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/application',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
the routing for home works fine. but for http://localhost/application I get:
Index(resolves to invalid controller class or alias: Index)
and for http://localhost/application/index/index I get:
index(resolves to invalid controller class or alias: index)
if I change this:
'application' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/application',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
to this:
'application' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/application',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
As you know definitely for http://localhost/application it will work fine like home url
if I use this:
'controllers' => array(
'invokables' => array(
'index' => 'Application\Controller\IndexController',
),
),
as you know the configurations will merge and I should have just one index controller in the project.
Why the line '__NAMESPACE__' => 'Application\Controller', be ignored and it looks for just Index or index in the controllers array which no exist??
EDIT:
With comparing to other projects I added this to Application/Module.php :
public function onBootstrap(MvcEvent $e)
{
$eventManager = $e->getApplication()->getEventManager();
$moduleRouteListener = new ModuleRouteListener();
$moduleRouteListener->attach($eventManager);
}
and it works now but I need and explanation. is it the solution? I mean should I add this to one of Module.php files in the project to make routing rules work fine? and why without it the __NAMESPACE__ will be ignored in routing rules?
You already found the solution, adding the ModuleRouteListener is the right thing to do. The explanation can be found in the description of the onRoute method inside this listener:
Listen to the "route" event and determine if the module namespace should be prepended to the controller name.
If the route match contains a parameter key matching the MODULE_NAMESPACE constant, that value will be prepended, with a namespace separator, to the matched controller parameter.
I'm creating a new small application with Zend Framework 2 and I've some problem with routes...
I've created a a new module cloning the Skeleton Module with Git and renaming it "Users". I've added controllers to register a new user, to login and to perform CRUD operations.
This is my module folder structure:
and this is my module.config.php file:
<?php
return array(
'controllers' => array(
'invokables' => array(
'Users\Controller\Index' => 'Users\Controller\IndexController',
'Users\Controller\Register' => 'Users\Controller\RegisterController',
'Users\Controller\Login' => 'Users\Controller\LoginController',
'Users\Controller\UserManager' => 'Users\Controller\UserManagerController',
),
),
'router' => array(
'routes' => array(
'users' => array(
'type' => 'Literal',
'options' => array(
// Change this to something specific to your module
'route' => '/users',
'defaults' => array(
// Change this value to reflect the namespace in which
// the controllers for your module are found
'__NAMESPACE__' => 'Users\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
// This route is a sane default when developing a module;
// as you solidify the routes for your module, however,
// you may want to remove it and replace it with more
// specific routes.
'login' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/login[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Users\Controller\Login',
'action' => 'index',
),
),
),
'register' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/register[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Users\Controller\Register',
'action' => 'index',
),
),
),
'user-manager' => array(
'type' => 'Segment',
'may_terminate' => true,
'options' => array(
'route' => '/user-manager[/:action[/:id]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Users\Controller\UserManager',
'action' => 'index',
),
),
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'users' => __DIR__ . '/../view',
),
),
);
When I try with my browser the url test.local/users/login or test.local/users/register everything works fine but if I try test.local/users/user-manager I get the following error:
Route with name "user-manager" not found
whilst with test.local/users/user-manager/edit/5 it is rendered the correct page.
I'm bit confused and I don't know how to solve this problem.
Any help is very appreciated. Thanks in advance.
problem solved! #AlexP was right, the problem was in index.phtl file with $this->url('user-manager');, I've changed in $this->url('users/user-manager') and now it works.
Thanks again!
I think the issue is with constraints and default values. Try to remove constraints in user-manager route and see what happen.
I added a reseller subdomain on my myhost.com (reseller.myhost.com) and I use it for routing to my Reseller module. Read this question I posted before here: click here
My Reseller route config looks this:
'router' => array(
'routes' => array(
'Reseller' => array(
'type' => 'Hostname',
'options' => array(
'route' => 'reseller.myhost.com',
'constraints' => array(
),
'defaults' => array(
'controller' => 'Reseller\Controller\Reseller',
'action' => 'index'
)
),
'may_terminate' => true,
'child_routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'__NAMESPACE__' => 'Reseller\Controller',
'controller' => 'Reseller',
'action' => 'index',
),
),
),
)
)
)
)
My createdAd route matches on reseller.myhost.com/createdAd but I expect routes from other modules not work on this reseller subdomain.
and here is my advertise route configuration
'router' => array(
'routes' => array(
'locate' => array(
'type' => 'segment',
'options' => array(
'route' => '/locate[/:cityName][/:CityId][/:CategoryId][/:categoryName]',
'constraints' => array(
),
'defaults' => array(
'controller' => 'Advertise\Controller\Advertise',
'action' => 'index',
),
),
),
'createAd' => array(
'type' => 'segment',
'options' => array(
'route' => '/createAd[/:subCategoryId]',
'constraints' => array(
),
'defaults' => array(
'controller' => 'Advertise\Controller\Advertise',
'action' => 'createAd',
),
),
),
),
),
));
be notice that i want to advertise module work without subdomain and work normally and only reseller module work with subdomain
Why does this occur?
I understand from your question: you expect the createAd route not to work on the subdomain. So reseller.myhost.com/createdAd should not match instead you want a to match on the route without subdomain myhost.com/createdAd.
I would suggest that you should create a separate route definition for the Advertise module.
Your route config in Advertise module (module/Advertise/config/module.config.php)
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Advertise\Controller\Advertise',
'action' => 'index'
)
),
)
'createAd' => array(
'type' => 'Literal',
'options' => array(
'route' => '/createAd',
'defaults' => array(
'controller' => 'Advertise\Controller\Advertise',
'action' => 'createAd',
)
)
)
)
)
Your route config in Reseller module (module/Reseller/config/module.config.php)
'router' => array(
'routes' => array(
'Reseller' => array(
'type' => 'Hostname',
'options' => array(
'route' => ':reseller.myhost.com',
),
'may_terminate' => false,
'child_routes' => array(
'home' => array(
'type' => 'Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Reseller\Controller\Reseller',
'action' => 'index'
)
)
)
)
)
)
),
You can distinguish matches because of the subdomain.
The routes home and createAdd match the Advertise module without subdomain.
The route reseller.home matches the index in Reseller module within subdomain reseller.myhost.com.
Check for more details also the Hostname routing example here in the ZF2 documentation
You should have a "root" hostname for all your standard routes not on the subdomain route. Eg:
'router' => array(
'routes' => array(
'myhost' => array(
'type' => 'Hostname',
'options' => array(
'route' => 'myhost.com',
),
),
),
),
Now you can add your 'createAd' route (and other routes) as a child route of the 'myhost' route. Eg:
'router' => [
'routes' => [
'myhost' => [
'child_routes' => [
'createAd' => array(
'type' => 'segment',
'options' => array(
'route' => '/createAd[/:subCategoryId]',
'constraints' => array(
),
'defaults' => array(
'controller' => 'Advertise\Controller\Advertise',
'action' => 'createAd',
),
),
),
],
],
],
],
I'm trying to achieve the routing explained in below but having a lot of trouble (the documentation is like a foreign language). Should routing for each module be kept separate in that module's config file?
"route": Module/Controller/Action
"/": Application/Index/index
"/:example": Application/Campaign/index (with param "campaign" = [example])
"/admin": Admin/Admin/index
"/admin/login": Admin/Access/login
"/admin/:controller/:action": Admin/[defined]/[defined]
I've tried to understand and use the skeleton application to do this and everything works up to the "/admin/controller/action" route where the script times out (I'm guessing there's a recursive loop in there somewhere). My route definitions are:
'home' => array(
'type' => 'literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
'campaign' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:campaign]',
'constraints' => array(
'campaign' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Application\Controller\Campaign',
'action' => 'index',
'campaign' => ''
),
),
),
'admin' => array(
'type' => 'segment',
'options' => array(
'route' => '/admin',
'defaults' => array(
'controller' => 'Admin\Controller\Admin',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
1) Yes, you should separate routing config to modules, ZF2 will merge it automatically. So you need to store home and campaign routes in Application/config/module.config.php and admin route in Admin/config/module.config.php
2) I don't see any global mistakes in your config. Two small things:
2.1) You can use literal instead of segment for admin parent route
2.2) If you want to use :controller as a route param, be sure to make shortcut for it via invokables section of config. For example:
'controllers' => array(
'invokables' => array(
'index' => 'Application\Controller\Index'
'admin' => 'Admin\Controller\Admin'
),
),
Now, for example, url /admin/admin/update is connected with Admin\Controller\Admin->updateAction()
3) I think it's not possible to make some recursive loops using only routing config. So check your code in controllers/services
i have a router test/view and i would like to pass some params like test/view/id/123.
Im not sure how to add those params in the zf2 router.
'router' => array(
'routes' => array(
'test' => array(
'type' => 'Literal',
'options' => array(
'route' => '/test',
'defaults' => array(
'__NAMESPACE__' => 'test\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'view' => array(
'type' => 'Literal',
'options' => array(
'route' => '/view',
'defaults' => array(
'controller' => 'Index',
'action' => 'view',
),
),
),
),
),
),
),
i setup view as a child route but not sure where to add those params.
i've tried 'route' => '/view/:id/:value' and
'defaults' => array(
'controller' => 'Index',
'action' => 'view',
'id' => 'value',
)
but they don't seem to work
i am trying to understand how all this works.
any ideas? thanks
'router' => array(
'routes' => array(
'test-view' => array(
'type' => 'segment',
'options' => array(
'route' => '/test/view/:testId[/]',
'constraints' => array(
'testId' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Test\Controller\Index',
'action' => 'view'
),
),
),
In your ControllerAction you can then get the parameter "testId" by using:
$this->params('testId');
Btw: The above route gives you an url like this: /test/view/123 - I thought you may get rid of the "id" param.
If you want to create a link to one kind of this pages, you can use $this->url('test-view', array('testId' => 123)) in one of your views.