Zend\Mvc\Router\Http\Method and child routes - php

i have defined two routes, /shoppingcart/ and a child route /shoppingcart/add/ which should only be available for POST requests.
'routes' => array(
'shoppingcart' => array(
'type' => 'literal',
'options' => array(
'route' => '/shoppingcart/',
'defaults' => array(
'controller' => 'ShoppingcartController',
'action' => 'shoppingcart',
),
),
'may_terminate' => true,
'child_routes' => array (
'add-product' => array(
'type' => 'method',
'options' => array(
'verb' => 'post',
'route' => 'add/',
'defaults' => array(
'controller' => 'ShoppingcartController',
'action' => 'addProductToShoppingcart',
),
),
),
)
),
)
The route /shoppingcart/ works fine. The child route /shoppingcart/add/ does not work(404 error with POST and GET).
When i change the type from method to literal and remove the verb key it works.
How can i use Zend\Mvc\Router\Http\Method in the child route?

You need to set may_terminate true for your child route.
Also, you mention route failing for GET, which it will if you only set the verb to post, if you want to allow get too, the verb should be get,post
Edit: after a little experimenting, it turns out my understanding was wrong, the Method type needs to be placed as parent of the route it's protecting....
'routes' => array(
'shoppingcart' => array(
'type' => 'literal',
'options' => array(
'route' => '/shoppingcart/',
'defaults' => array(
'controller' => 'ShoppingcartController',
'action' => 'shoppingcart',
),
),
'may_terminate' => true,
'child_routes' => array (
'add-product' => array(
'type' => 'method',
'options' => array(
'verb' => 'get,post',
),
'child_routes' => array(
// actual route is a child of the method
'form' => array(
'may_terminate' => true,
'type' => 'literal',
'options' => array(
'route' => 'add/',
'defaults' => array(
'controller' => 'ShoppingcartController',
'action' => 'addProductToShoppingcart',
),
),
),
),
),
),
),
),

Related

zend framework 2 routing going to incorrect action

I am trying to hit the datatable action with the sID and cID params.
/CustomerManager/datatable/123/100
When the above url is hit it goes to the refreshdata see below image.
Working fine when the url is
/CustomerManager/datatable
Can anyone see problem with the config?
'CustomerManager' => array(
'type' => 'Segment',
'options' => array(
'route' => '/CustomerManager[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'CustomerManager\Controller\CustomerManager',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'datatable' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:sID][/:cID]',
'constraints' => array(
'cono' => '[a-zA-Z0-9_-]+',
'cust' => '[a-zA-Z0-9_-]+',
),
'defaults' => array(
'action' => 'datatable',
),
),
),
'refreshdata' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:showDel][/:sID][/:cID]',
'defaults' => array(
'action' => 'refreshdata'
),
'constraints' => array(
'showDel' => '[a-zA-Z0-9_-]+',
'sID' => '[a-zA-Z0-9_-]+',
'cID' => '[a-zA-Z0-9_-]+',
)
)
),
)
it seems "refreshdata" overwrite "datatable" because you expect a url with at last 3 parameter which all can be letters or numbers
and in request you call a url with two number type parameters which matches with "refreshdata"
also I think
'cono' => '[a-zA-Z0-9_-]+',
'cust' => '[a-zA-Z0-9_-]+',
in this line "cono" and "cust" must change to "sID" and "cID"
After my comment an example on how you declare your routes more structured:
'router' => array(
'CustomerManager' => array(
'CustomerManager' => array(
'type' => 'literal',
'options' => array(
'route' => '/CustomerManager',
'defaults' => array(
'controller' => 'Application\Controller\IndexController',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
// Literal route for data table
'datatable' => array(
'type' => 'literal',
'options' => array(
'route' => '/datatable',
'defaults' => array(
'action' => 'datatable',
),
),
'may_terminate' => true,
'child_routes' => array(
// Child route for table cell
'cell' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:sID][/:cID]',
'constraints' => array(
'sID'=> '[a-zA-Z0-9_-]+',
'cID' => '[a-zA-Z0-9_-]+',
),
),
),
),
),
// Literal route for refreshtable
'refreshtable' => array(
'type' => 'literal',
'options' => array(
'route' => '/refreshtable',
'defaults' => array(
'action' => 'refreshtable',
),
),
'may_terminate' => true,
'child_routes' => array(
// Child route for table cell
'cell' => array(
'type' => 'segment',
'options' => array(
'route' => '/[:sID][/:cID]',
'constraints' => array(
'sID'=> '[a-zA-Z0-9_-]+',
'cID' => '[a-zA-Z0-9_-]+',
),
),
),
),
),
),
),
),
)
This is simply an example you can change it after your specific needs.
EDIT
Understanding the basics of routing is important for building a proper application. You should read the ZF2 Routing documentation thoroughly, all the information you need is in there...
For example:
In the question the sID and cID segments are optional (between square brackets). This will most likely also not work as you expect. A problem might occur when column cID is given but no sID value is given. The router will attach the cID value to the sID parameter name in such case, leading to unexpected route parameter values in your match.
Something like this could be solved by doing something like this with your constraints:
'constraints' => array(
'sID' => 's[a-zA-Z0-9_-]+',
'cID' => 'c[a-zA-Z0-9_-]+'
),
By preceding the regular expression constraints (and the values in the url) with either an s or a c you make sure the correct value is tied to the correct parameter.

Zend framework 2 format url with parameters

what do I need to write in the module.config file to accept a route in the folowing format?
/action/parameter/value
I think in ZF1 this was done by default
Thank you
Here Is my route, I tried but I just can't get it to work
what route I need is classes/less/value
where less is a query parameter
'classes' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:lang/classes',
'defaults' => array(
'__NAMESPACE__' => 'Classes\Controller',
'controller' => 'Classes',
'action' => 'index',
'lang' => 'en',
),
),
'may_terminate' => true,
'child_routes' => array(
'process' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:action]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'lang' => '[a-z]{2}',
),
'defaults' => array(
),
),
),
),
),
To help you more, we will need to see your current routing.
You will basically need a simple segment route with your action, followed by an open wildcard non required section:
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/products[/:action]',
'defaults' => array(
'controller' => 'Application\Controller\Products',
'action' => 'index'
)
),
'may_terminate' => true,
'child_routes' => array(
'wildcard' => array(
'type' => 'Wildcard'
)
)
)
If I understand correctly you would like your route to contain a parameter. The way i updated your code below you are able to add one more constraint in your route. So it is action/less/lang. Consider the updated code below assuming i understood what you are trying to do.
'classes' => array(
'type' => 'Segment',
'options' => array(
'route' => '/:lang/classes',
'defaults' => array(
'__NAMESPACE__' => 'Classes\Controller',
'controller' => 'Classes',
'action' => 'index',
'lang' => 'en',
),
),
'may_terminate' => true,
'child_routes' => array(
'process' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:action]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'less' => '[a-zA-Z0-9_-]*',//edit here
'lang' => '[a-z]{2}',
),
'defaults' => array(
),
),
),
),
),

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!

ZF2 Child route issues

I am trying to get some basic routing done in ZF2 but I am running into some problems.
The section that is giving me trouble is this:
'parent-categories' => array(
'type' => 'literal',
'options' => array(
'route' => '/kategorier/',
'defaults' => array(
'controller' => 'categories',
'action' => 'parent-categories',
),
),
'may_terminate' => true,
'child_routes' => array(
'child-categories' => array(
'type' => 'segment',
'options' => array(
'route' => '/kategorier[/:slug][/:parentCategoryid]/',
'constraints' => array(
'parentCategoryid' => '[0-9]+',
),
'defaults' => array(
'controller' => 'categories',
'action' => 'child-categories',
)
),
),
),
),
The original 'parent-categories' route works just fine, no problem. The problem though is the child-categories route isn't doing anything. I have the URL:
/kategorier/test-test-test-test-test/1/
but this is never matched to anything. I get the error:
The requested URL could not be matched by routing.
If I take the child-categories route out of the "child_routes" section, it always catches the request, even if the url is only /kategorier/. Can anyone see what I am doing wrong here?
A child route appends to the parent route. I.e. what you're currently matching is
/kategorier//kategorier[/:slug][/:parentCategoryid]/
Do it like this
'parent-categories' => array(
'type' => 'literal',
'options' => array(
'route' => '/kategorier',
'defaults' => array(
'controller' => 'categories',
'action' => 'parent-categories',
),
),
'may_terminate' => true,
'child_routes' => array(
'child-categories' => array(
'type' => 'segment',
'options' => array(
'route' => '[/:slug][/:parentCategoryid]',
'constraints' => array(
'parentCategoryid' => '[0-9]+',
),
'defaults' => array(
'controller' => 'categories',
'action' => 'child-categories',
)
),
),
),
),
And i guess this should be working out alright. It's a good advice to NOT have trailing slashes, as you'd ideally always want to begin new routes with one for better readability ;)

how to pass params using a route in Zend Framework 2?

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.

Categories