Routes with multiple modules - php
I'm currently working in ZF2 and need some help.
Unfortunately I can only find examples set the routes for the case that there is only one module. Or the example has still the application module in it, with dynamic segment routes. I want to totally remove the application module and only have my own modules running an configure all routing in them.
I have two modules:
CLFrontend,
CLBackend
My application config looks like this:
return array(
'modules' => array(
'ClFrontend',
'ClBackend'
),
'module_listener_options' => array(
'config_glob_paths' => array(
'config/autoload/{,*.}{global,local}.php',
),
'module_paths' => array(
'./module',
'./vendor',
),
),
);
I want to register my 2 own modules there. The routing should now look someway like this:
everything under / should go to the frontend module excerpt /backend
/ --> IndexController --> indexaction
/controller1 --> Controller1Controller -> indexaction
/controller1/add --> Controller1Controller --> addaction
/controller1/add/1/ --> COntroller1Controller --> addaction --> item 1
Now should everything under /backend route to the backend module
/backend --> BackendIndexController --> indexaction
/backend/controller1 --> BackendController1Controller -> indexaction
/backend/controller1/add --> BackendController1Controller -->
addaction
/backend/controller1/add/1/ --> BackendCOntroller1Controller -->
addaction --> item 1
And i want to define that routes fixed and not something like a segment route looking like that:
:module/:controller/:action
I want to end up with something like
/
/controller1/[:action[/:id]]
AND
/backend
/backend/backendcontroller/[:action[/:id]]
Myapproach was the following. The problem is now, that even the backend routes seem to match to the frontend module?! I either get a 404 with
The requested URL could not be matched by routing.
Or
Fatal error: Class 'ClBackend\Controller\AnswerController' not found
in
//*/**/***/checklistenassistent3/vendor/ZF2/library/Zend/ServiceManager/AbstractPluginManager.php
on line 177
CLFrontend/config/module.config.php
return array(
'controllers' => array(
'invokables' => array(
'ClFrontend\Controller\Index' => 'ClFrontend\Controller\IndexController',
'ClFrontend\Controller\User' => 'ClFrontend\Controller\UserController',
),
),
'router' => array(
'routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'ClFrontend\Controller\Index',
'action' => 'index',
),
),
),
),
),
'view_manager' => array(
'display_not_found_reason' => true,
'display_exceptions' => true,
'doctype' => 'HTML5',
'not_found_template' => 'error/404',
'exception_template' => 'error/index',
'template_map' => array(
'layout/layout' => __DIR__ . '/../view/cl-frontend/layout/layout.phtml',
'application/index/index' => __DIR__ . '/../view/cl-frontend/index/index.phtml',
'error/404' => __DIR__ . '/../view/cl-frontend/error/404.phtml',
'error/index' => __DIR__ . '/../view/cl-frontend/error/index.phtml',
),
'template_path_stack' => array(
__DIR__ . '/../view',
),
),
);
CLBackend/config/module.config.php
return array(
'controllers' => array(
'invokables' => array(
'ClBackend\Controller\Answer' => 'ClBackend\Controller\AnswerController',
'ClBackend\Controller\AnswerGroup' => 'ClBackend\Controller\AnswerGroupController',
'ClBackend\Controller\Category' => 'ClBackend\Controller\CategoryController',
'ClBackend\Controller\Checklist' => 'ClBackend\Controller\ChecklistController',
'ClBackend\Controller\Index' => 'ClBackend\Controller\IndexController',
'ClBackend\Controller\Question' => 'ClBackend\Controller\QuestionController',
'ClBackend\Controller\User' => 'ClBackend\Controller\UserController',
),
),
'router' => array(
'routes' => array(
'backend' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/backend',
'defaults' => array(
'controller' => 'ClBackend\Controller\Index',
'action' => 'index',
),
'may_terminate' => true
),
'child_routes' => array (
'answer' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/answer/:action/:id',
'defaults' => array(
'controller' => 'ClBackend\Controller\Answer',
'action' => 'index',
),
),
),
'answergroup' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/answergroup/:action/:id',
'defaults' => array(
'controller' => 'ClBackend\Controller\AnswerGroup',
'action' => 'index',
),
),
),
'category' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/category/:action/:id',
'defaults' => array(
'controller' => 'ClBackend\Controller\Category',
'action' => 'index',
),
),
),
'checklist' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/checklist/:action/:id',
'defaults' => array(
'controller' => 'ClBackend\Controller\Checklist',
'action' => 'index',
),
),
),
'question' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/question/:action/:id',
'defaults' => array(
'controller' => 'ClBackend\Controller\Question',
'action' => 'index',
),
),
),
'user' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/user/:action[/:id]',
'defaults' => array(
'controller' => 'ClBackend\Controller\User',
'action' => 'index',
),
),
),
),
),
),
),
);
Have you considered a Controller factory? It would allow you to match a single route and use logic to decide on which controller to use.
For example your route could look like:
'backend-default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:controller_type[/:action][/id]',
'defaults' => array(
'action' => 'index',
'controller' => 'MyFactory'
),
),
),
If this route was matched then the Controller factory (MyFactory) would be used - within this factory you can gain access to the route match parameters. Using these parameters you should be able to return the appropriate controller.
You could even pass in an additional parameter signifying it's a backend controller (and use a single factory).
use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
class MyFactoryController implements FactoryInterface
{
public function createService(ServiceLocatorInterface $serviceLocator)
{
// $serviceLocator is a Zend\Mvc\Controller\ControllerManager
$app = $serviceLocator->getServiceLocator()->get('application');
$routeMatch = $app->getMvcEvent()->getRouteMatch();
var_dump($routeMatch);
/**
* Create controller based off $routeMatch params
*/
return $controller;
}
}
The controller factory would allow you to lookup the controller_type variable to a valid class name - or prefix an invokable name to controller_type.
I'm not sure I'd take this route myself but I hope this is somewhat useful for what you are trying to achieve.
Related
ZF2 - The requested URL could not be matched by routing
i receive this error when i go to localhost/app/public/spanel/test/index This application have a sPanel module. Into it have a TestController with indexAction() This is the sPanel\config\module.config.php <?php return array( 'controllers' => array( 'invokables' => array( 'sPanel\Controller\Test' => 'sPanel\Controller\TestController', ), ), 'router' => array( 'routes' => array( 'spanel' => array( 'type' => 'segment', 'options' => array( 'route' => '/test[/:action][/:id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'sPanel\Controller\Test', 'action' => 'index', ), ), ), ), ), 'view_manager' => array( 'template_path_stack' => array( 'spanel' => __DIR__ . '/../view', ), ), );
First of all i strongly suggest that you start working with virtual hosts to get rid of that annoying localhost/bla/public Second of all things, you try to access this route: yourdomain/spanel/test/index, but there is no indication of you assigning the part /spanel anywhere in your route, all you assign is /test[...] So in short, you want to access yourdomain/test/index or you want to modify your route to inclide the /spanel part
Routing in Zend Framework 2
I'm trying to do some routing in Zend Framework 2, but it's not working. The basics of the skeleton application are working, so I added a new module called User and the following code in the file \module\User\config\module.config.php 'controllers' => array( 'invokables' => array( 'User\Controller\User' => 'User\Controller\UserController', ), ), 'router' => array( 'routes' => array( 'login' => array( 'type' => 'Literal', 'options' => array( 'route' => '/login', 'defaults' => array( '__NAMESPACE__' => 'User\Controller', 'controller' => 'User', 'action' => 'login', ), ), ), 'user_create' => array( 'type' => 'Literal', 'options' => array( 'route' => '/user/create', 'defaults' => array( '__NAMESPACE__' => 'User\Controller', 'controller' => 'User', 'action' => 'create', ), ), ), ), ), If I try to access the first route (/login), it works. But the second route (/user/create) results in the error: File: F:\www\ZendVendas\library\Zend\Mvc\Router\Http\TreeRouteStack.php:313 Message: Route with name "create" not found If I do create a route without the controller name, it works: 'create' => array( 'type' => 'Literal', 'options' => array( 'route' => '/create', 'defaults' => array( '__NAMESPACE__' => 'User\Controller', 'controller' => 'User', 'action' => 'create', ), ), ), But I would want the route were "/user/create", and don't "/create". I have searched for many topics, but can't see where is my mistake. Appreciate any help ;) Edit: ajusted code with suggestions of #Jurian 'router' => array( 'routes' => array( 'user' => array( 'type' => 'Literal', 'options' => array( 'route' => '/user', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'profile', ), ), 'child_routes' => array( 'login' => array( 'type' => 'Literal', 'options' => array( 'route' => '/login', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'login', ), ), ), 'create' => array( 'type' => 'Literal', 'options' => array( 'route' => '/create', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'create', ), ), ), ), ), ), ),
You have to understand how routing works in Zend Framework 2. Routes have a name and some configuration. The structure looks as follows: 'router' => array( 'routes' => array( 'route_name_1' => array( /* config here */ ), 'route_name_2' => array( /* config here */ ), 'route_name_3' => array( /* config here */ ), ), ), Here the route names are route_name_1 etc. If you assemble an url, you use that route name. So if route_name_1 has the url /foo/bar/baz, you can ask for the url of route_name_1 by using the url view helper: echo $this->url('route_name_1'); // prints /foo/bar/baz Your url /user/create is mapped to the route name user_create so to assemble this url, you need to pass on the route name: echo $this->url('user_create'); // prints /user/create CHILD ROUTES There is also a concept of child routes. This can give you a route user which maps to /user and then this user route has a child create which maps to /create and as such the "total" route of create is /user/create. This can be configured as follows: 'router' => array( 'routes' => array( 'route_name_1' => array( /* config here */ ), 'route_name_2' => array( /* config here */ 'child_routes' => array( 'child_name_1' => array( /* config here */ ), 'child_name_2' => array( /* config here */ ), ), ), ), ), Now, if you want to assemble an url for route_name_2 it just looks as above: echo $this->url('route_name_1'); But if you need to assemble the url for child_name_1 you construct a "path" with a / between the name and its parent(s): echo $this->url('route_name_1/child_name_1'); So although you can access the /user/create route fine with the route name you already have, you might want to use child routes as this gives you a more flexible routing system: 'router' => array( 'routes' => array( 'user' => array( 'type' => 'Literal', 'options' => array( 'route' => '/user/create', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'profile', ), ), ), 'child_routes' => array( 'login' => array( 'type' => 'Literal', 'options' => array( 'route' => '/login', 'defaults' => array( 'action' => 'login', ), ), ), 'create' => array( 'type' => 'Literal', 'options' => array( 'route' => '/create', 'defaults' => array( 'action' => 'create', ), ), ), ), ), ), ), Then you have a route user which maps to a "profile". If you assemble user/create you go to /user/create and it uses the "createAction" from the user controller. The same hapens with user/login route.
I have found what I was doing wrong. In one of my view files, there was a URL function pointing to the route /create. It would be much helpful if Zend indicated the file with the invalid route, but, once I found the mistake, everything is working now. 'router' => array( 'routes' => array( 'login' => array( 'type' => 'Literal', 'options' => array( 'route' => '/login', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'login', ), ), ), 'logout' => array( 'type' => 'Literal', 'options' => array( 'route' => '/logout', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'logout', ), ), ), 'user' => array( 'type' => 'Literal', 'options' => array( 'route' => '/user', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'profile', ), ), 'child_routes' => array( 'create' => array( 'type' => 'Literal', 'options' => array( 'route' => '/create', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'create', ), ), ), 'edit' => array( 'type' => 'Literal', 'options' => array( 'route' => '/edit', 'defaults' => array( 'controller' => 'User\Controller\User', 'action' => 'edit', ), ), ), ), ), ), ), Thank you for the help!
Multiple routes under same tree in ZF2
I am having problem while implementing Multiple routes as defined Below in my snippet EDIT: i am getting this exception too Additional information: Zend\Mvc\Exception\InvalidControllerException with Message Controller of type Account\Controller\VoucherController is invalid; must implement Zend\Stdlib\DispatchableInterface <?php namespace Account; return array( 'controllers' => array( 'invokables' => array( 'Account\Controller\Account' => 'Account\Controller\AccountController', 'Account\Controller\Voucher' => 'Account\Controller\VoucherController', ), // --------- Doctrine Settings For the Module 'doctrine' => array( 'driver' => array( 'account_entities' => array( 'class' => 'Doctrine\ORM\Mapping\Driver\AnnotationDriver', 'cache' => 'array', 'paths' => array(__DIR__ . '/../src/Account/Entity') ), 'orm_default' => array( 'drivers' => array( 'Account\Entity' => 'account_entities' ) ) ) ), // The following section is new and should be added to your file 'router' => array( 'routes' => array( 'account' => array( 'type' => 'segment', 'options' => array( 'route' => '/account[/][:action][/:id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Account\Controller\Account', 'action' => 'index', ), ), ), 'voucher' => array( 'type' => 'segment', 'options' => array( 'route' => '/account/voucher[/][:action][/:id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Account\Controller\Voucher', 'action' => 'index', ), ), ), ), ), 'view_manager' => array( 'template_path_stack' => array( 'account' => __DIR__ . '/../view', ), ), ), ); Now the issue is i am getting a 404, when i try to access MyHost/account/Voucher P.S: I already have A Controller under Account/Controller/Voucher and a view under Account/View/Voucher named as index.phtml now i dont know what am i missing here.
As Adnrew and Timdev comments above that there is something not right in your controller, you can check few basic things in your controller, that you have following code correct. specially the typos. namespace Account\Controller; use Zend\Mvc\Controller\AbstractActionController; use Zend\View\Model\ViewModel; class VoucherController extends AbstractActionController { // you acctions }
ZF2 run the application without using the router
I am learning ZF2. Is it possible to run the application without Router as in Zf1? Do we need to define router for each controller? Example: In ZF1: "admin/index/index" shows as "module/controller/action" IN ZF2: "admin/index/index" shows as "router[/:controller][/:action]" please help me to clear my doubts.
Please tyr this return array( // routes 'router' => array( 'routes' => array( 'album' => array( 'type' => 'Literal', 'options' => array( 'route' => '/album', 'defaults' => array( 'controller' => 'album\Controller\Index', '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( // add the default namespace for :controllers in this route '__NAMESPACE__' => 'album\Controller', ), ), ), ), ), ), ), 'controllers' => array( 'invokables' => array( 'album\Controller\Test' => 'Album\Controller\TestController', ), ), 'view_manager' => array( 'template_path_stack' => array( 'album' => __DIR__ . '/../view', ), ), ); You need to add your controller name in invokables manually or invoke via Abstract Factories 'controllers' => array( 'invokables' => array( 'album\Controller\Test' => 'Album\Controller\TestController', ), ), Automatic Controller Invokables via Abstract Factories Reference
Unable to render template zf2
I have created new module called 'currency' and configured routes in module.config. It is working fine. After that I have added new controller called CrateController for currency rates.And also created forms, models and view files. But It is not routing correctly. Error: Fatal error: Uncaught exception 'Zend\View\Exception\RuntimeException' with message 'Zend\View\Renderer\PhpRenderer::render: Unable to render template "currency/crate/index"; resolver could not resolve to a file.... Any clue to check this out will be helpful. My module.config file as follows. return array( 'controllers' => array( 'invokables' => array( 'Currency\Controller\Currency' => 'Currency\Controller\CurrencyController', 'Currency\Controller\Crate' => 'Currency\Controller\CrateController', ), ), // The following section is new and should be added to your file 'router' => array( 'routes' => array( 'currency' => array( 'type' => 'segment', 'options' => array( 'route' => '/currency[/:action][/:currency_id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'currency_id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Currency\Controller\Currency', 'action' => 'index', ), ), ), 'crate' => array( 'type' => 'segment', 'options' => array( 'route' => '/crate[/:action][/:c_rate_id]', 'constraints' => array( 'action' => '[a-zA-Z][a-zA-Z0-9_-]*', 'c_rate_id' => '[0-9]+', ), 'defaults' => array( 'controller' => 'Currency\Controller\Crate', 'action' => 'index', ), ), ), ), ),
Check for two things: First: Is the template file present? ./module/Currency/view/currency/crate/index.phtml Second: Check for the following entry inside ./Currency/config/module.config.php 'view_manager' => array( 'template_path_stack' => array( 'currency' => __DIR__ . '/../view', ) ),