I have configured a route in my module.config.php to handle two parameters ,
here is the content of the file module.config.php , i put just the definition of the routes ( same routes ) :
updated :
'router' => array(
'routes' => array(
'Products' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/application/admin/products[/:id]',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Admin',
'action' => 'index',
),
),
),
'productsList' => array(
'type' => 'segment',
'options' => array(
'route' => '/application/products/productsList[/:type][/:id]',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Products',
'action' => 'productsList'
),
),
),
'Emplacement' => array(
'type' => 'segment',
'options' => array(
'route' => '/application/support/listeEmplacementsSupport[/:pkSupport]',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Support',
'action' => 'listeEmplacementsSupport',
),
),
),
'application' => array(
'type' => 'Literal',
'options' => array(
'route' => '/application',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action[/:id][/:dr]]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
),
),
),
),
),
),
),
And I build a link in the view using the following
<a href="/application/products/productsList/mandan/<?php echo $coreg['idProduct']; ?>" >
<img height='20' src="/img/mail-recevoir-32.png" alt='products' />
</a>
To get one parameter I use
$param = $this->params('id');
Routes are matched in the 'Last in first out' LIFO order.
The relevant section of the documentation states:
Typically, routes should be queried in a LIFO order, and hence the reason behind the name RouteStack. [...] you will need to ensure that routes that potentially overlap are registered such that the most specific match will match first (i.e., register later)
Therefore based on you current configuration, as all the routes are register at the top level, the last route (application/default) is being checked and then subsequently matched first, before the productList is given a chance.
Also because application/default defines an optional id parameter as the first argument this is the reason that you get the value of the type param when using $this->params('id').
Soultion
The easiest solution is just to reorder the routes; moving the application route right to the top of the definition should work.
The order should be the following
'router' => array(
'routes' => array(
'application' => array(
// .. same
'child_routes' => array(
'default' => array(
// .. Same
),
),
),
'Products' => array(
// ..same
),
'productsList' => array(
// ..same
),
'Emplacement' => array(
// ..config
),
),
),
You could alternatively give each route a priority, regardless of the order, however I think It would make more sense to keep them in a natural order to save confusion in the future.
While I'm here
I mentioned in my comment you incorrectly used a Literal route rather than a Segment. You have this same issue with the the Products route definition. If a route is literal it will only match on the exact value (so you would need /[:id] in the URL).
/application/admin/products[/:id]
Therefore you will also need to update this route to a segment in order for the product id to be regarded as a parameter.
Lastly, there is a easier way of constructing URL's in the view, using the URL view helper. Your view script code would be changed to
<?php
$type = 'mandan';
$id = $coreg['idProduct'];
?>
<a href="<?php echo $this->url('productsList', compact('type', 'id')); ?>">
<img height='20' src="/img/mail-recevoir-32.png" alt='products' />
</a>
Related
This is my last chance. I tried loooking for answers, but seriously, I can't see what I'm doing wrong...
I'm trying to set up a multi-domain on a website.
Everything is working fine when using literal routes.
When adding the other domain with Hostname route, still OK.
But when adding child_routes to that Hostname route, the parent route shoots a 404.
Here's my module.config :
'resources' => $resources,
'router' => array(
'routes' => array(
'example.com' => array(
'type' => 'Zend\Mvc\Router\Http\Hostname',
'options' => array(
'route' => '[:subdomain.]:domain.:tld', // domain levels from right to left
'contraints' => array(
'subdomain' => 'www',
'domain' => 'example',
'tld' => 'com',
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'itdoc',
),
),
'may_terminate' => true,
'child_routes' => array(
'customCatalog2' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/custom-catalog',
'defaults' => array(
'action' => 'customCatalog',
),
),
),
When accessing http://example.com, I'm getting a 404.
But the child route works fine (http://example.com/custom-catalog)
But if I comment out the child_routes (and may_terminate), I can access the root domain
Do you have any clue of what is wrong with my code ?
Thanks !!!
I test your code and in fact this is weird, but after some test and read the docs here is what i Found.
This documentaiton help
^
I looked forward to this component and found in the docs this :
'packages.zendframework.com' => array(
'type' => 'Zend\Mvc\Router\Http\Hostname',
'options' => array(
'route' => ':4th.[:3rd.]:2nd.:1st', // domain levels from right to left
'contraints' => array(
'4th' => 'packages',
'3rd' => '.*?', // optional 3rd level domain such as .ci, .dev or .test
'2nd' => 'zendframework',
'1st' => 'com',
),
// Purposely omit default controller and action
// to let the child routes control the route match
),
// child route controllers may span multiple modules as desired
'child_routes' => array(
'index' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Package\Controller\Index',
'action' = > 'index',
),
),
'may_terminate' => true,
),
),
),
As you can see, they have child route but the first route declared is the route match this pattern : '/', this is your main route you have to declare this equal to your code below :
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'itdoc',
),
After that, your main route is correct and you can continue with other child route, just the hostname is not the actual main route '/'.
I have a /files controller that will have two actions: upload and download
it's defined as follows:
'files' => array(
'type' => 'Segment',
'options' => array(
'route' => '/files[/:action]',
'defaults' => array(
'controller' => 'Application\Controller\Files',
'action' => 'index',
),
),
),
I want the download action to be accessed like /files/download/1?authString=asdf. 1 in this case is a fileId.
I understand I can just change the route to /files[/action[/:fileId]] to set up the route, correct me if I'm wrong, but then how do I access the fileId inside the downloadAction? And is there anything else I need to change about the route definition to make it work??
I can just change the route to /files[/action[/:fileId]] to set up the route, correct me if I'm wrong
You're not wrong, that would be a valid route.
is there anything else I need to change about the route definition?
If you add the fileId as a optional route param then you will need to do some manual checking within the downloadAction() to ensure it is set.
Another solution would be to separate the routes into children, this ensures that unless you have the correct parameters on each route, it would not be matched.
'files' => array(
'type' => 'Segment',
'options' => array(
'route' => '/files',
'defaults' => array(
'controller' => 'Application\Controller\Files',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'download' => array(
'type' => 'Segment',
'options' => array(
'route' => '/download/:fileId',
'defaults' => array(
'action' => 'download',
),
'constraints' => array(
'fileId' => '[a-zA-Z0-9]+',
),
),
),
'upload' => array(
'type' => 'Literal',
'options' => array(
'route' => '/upload',
'defaults' => array(
'action' => 'upload',
),
),
),
),
),
how do I access the fileId inside the downloadAction
The easiest way would be to use the Zend\Mvc\Controller\Plugin\Params controller plugin to fetch the parameter from the route).
// FilesController::downloadAction()
$fileId = $this->params('fileId');
Or specifically from the route
// FilesController::downloadAction()
$fileId = $this->params()->fromRoute('fileId');
My root url is http://restaurent.local
i want to route like this http://restaurent.local/menuedit/test/1. But this not working
This is my code
'menuedit' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/menuedit[/:action][/:id]',
'defaults' => array(
'controller' => 'Menu\Controller\Menu',
'action' => 'menuedit',
),
),
),
if any one know about this please help me.
You're attempting to use a Literal route type. You need a Segment route type if you want to match your route parameters ...
'menuedit' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/menuedit[/:action][/:id]',
'defaults' => array(
'controller' => 'Menu\Controller\Menu',
'action' => 'menuedit',
),
),
),
Please consider reading the manual to understand the differences and how they're meant to be used -> http://framework.zend.com/manual/2.3/en/modules/zend.mvc.routing.html#http-route-types
You might also want to set your constraints for the route parameters. I'd also make the trailing backslash optional with [/] otherwise it won't match /route/to/ it would only match /route/to
'menuedit' => array(
'type' => 'segment',
'options' => array(
'route' => '/menuedit[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => [0-9]*'
),
'defaults' => array(
'controller' => 'Menu\Controller\Menu',
'action' => 'menuedit',
),
),
),
I Literal route can't handle params.
'type' => 'Zend\Mvc\Router\Http\Literal',
You want to edit a specific menu, with specific id, this is a param.
For handle param you have to use Segment type.
Don't forget to add constraints option for your action AND your id. More secure.
How to allow all sub actions inside that controller with one router rule? For example this follow:
visit: site/login - works only
site/login/forgetpassword - does not work
site/login/remmeberme - does not work
Example:
$router = $e->getApplication()->getServiceManager()->get('router');
$route = Http\Literal::factory(array(
'route' => '/login',
'defaults' => array(
'controller' => 'Application\Controller\Login',
'action' => 'index'
),
));
$router->addRoute('login', $route, null);
Follow up:
How can i make it so that /login and /login/anything works?
$route = Http\Segment::factory(array(
'route' => '/login[/:action]',
'defaults' => array(
'controller' => 'Application\Controller\Login',
'action' => 'index'
),
));
$router->addRoute('login', $route, null);
There is an excellent QuickStart Tutorial available within the official Documentation. Set up your route like the following to be allowed multiple actions and an ID Parameter. Fur further information please take a look at the documentation.
You may also be interested in DASPRiDs presentation from ZendCon2012
'router' => array(
'routes' => array(
'album' => array(
'type' => 'segment',
'options' => array(
'route' => '/album[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Album\Controller\Album',
'action' => 'index',
),
),
),
),
),
Build navigation from config:
'navigation' => array(
'default' => array(
'admin' => array(
'label' => 'Administration',
'controller' => 'index',
'action' => 'index',
'route' => 'admin/default',
),
'album' => array(
'label' => 'Album',
'controller' => 'index',
'action' => 'index',
'route' => 'album/default',
),
/* ... */
Routing is configured like it is true. Navigation in the menu works. Links menu lead to the desired controller/action of the desired module. But while introducing menu and a transition to one or another menuitem, active marked both points simultaneously and 'Administration' and 'Album'. As I understand it, for the reason that match the names of controllers and actions with them, but there's still the 'route' and it's different... not for nothing that the generated different url for each item... but somehow, despite this, they both are marked as active.
Routing config:
'router' => array(
'routes' => array(
'admin' => array(
'type' => 'Literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'__NAMESPACE__' => 'Admin\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller][/:action[/id:id]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
),
),
),
Album routing config similar...
Why this is happening? Thanks.
Looks like it's how ZF2 works (read isActive() function in Zend\Navigation\Page\Mvc.php). Initially it checks matching of route/controller/action, but if it fails, ZF2 again check for just controller/action pair. So there are three possible ways:
Open a ticket at https://github.com/zendframework/zf2/issues and wait for response.
Override \Zend\Navigation\Page\Mvc.
Choose different names for controllers (and don't use index name because it's default name for controller in Mvc.php).
If you make your controller names include the the namespace then they will be unique and won't clash:
Admin\Controller\IndexController
Album\Controller\IndexController
Rather than
Index
Index