I have the following route in my module.config.php:
'routes' => array(
'admin' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin[/:controller[/:action]][/]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]+',
'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
),
'defaults' => array(
'__NAMESPACE__' => 'Admin\Controller',
'module' => 'Admin',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'wildcard' => array(
'type' => 'Wildcard',
)
),
'priority' => 1000
),
),
The reason for the [/] in the end of the route is in the question: Zend Framework 2 Segment Route matching 'test' but not 'test/'
I want this route to be like in ZF1. I want to pass $_GET parameters in it (like /id/1/test/2/).
The problem it this route is actually matching /admin/customer/edit//id/20 but not matching /admin/customer/edit/id/20
Any ideas?
You are on the right track! Use "Wilcard" as a type of child-route to your admin-route.
There are two options available: key_value_delimiter and param_delimiter.
Both's default values are '/' which is equal to the ZF1 default behaviour of route parameters.
'router' => array(
'routes' => array(
'admin' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin[/:controller[/:action]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]+',
'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
),
),
'defaults' => array(
'__NAMESPACE__' => 'Admin\Controller',
'module' => 'Admin',
'controller' => 'Index',
'action' => 'index',
),
'may_terminate' => true,
'child_routes' => array(
'wildcard' => array(
'type' => 'Wildcard',
'options' => array(
'key_value_delimiter' => '/',
'param_delimiter' => '/'
)
)
)
)
)
)
If you want to address the wildcard route with the help of the url view-helper, you can use it like that:
$this->url('admin/wildcard', array('id' => 1234, 'foo' => 'bar'));
You can add route parameter for id :
'route' => '/admin[/:controller[/:action]][/:id][/]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]+',
'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
'id' => '[0-9]+',
),
this route matchs admin/customer/edit/20/, so you can get id in controller:
$this->params()->fromRoute('id');
If you want to have admin/customer/edit/id/20/ ,try:
'route' => '/admin[/:controller[/:action]][id/:id][/]',
If I am understanding correctly, you are trying to get multiple parameters from the URL, right?
e.g.
Traditional GET: www.domain.com/ctrl/action?key1=abc&key2=efg& ... & keyN=xyz
ZF2 route: www.domain.com/ctrl/action/key1/abc/key2/efg/.../keyN/xyz
If so, this is one way of doing it:
'adminPage' => array(
'type' => 'regex',
'options' => array(
'regex' => '/admin/customer/edit[/](?<keyValuePairs>.*)',
'defaults' => array(
'controller' => 'YourProject\Controller\YourController',
'action' => 'yourAction',
),
'spec' => '/admin/customer/edit/%keyValuePairs%',
)
With this, every character after 'admin/customer/edit/' will be stored in 'keyValuePairs' parameter. In Controller::yourAction, get the 'keyValuePairs' parameter, then split the string back into a meaningful key-value data structure.
Related
I have application with following URLs
www.myapp.com/admin/profile [index action]
www.myapp.com/admin/profile/add [add action]
www.myapp.com/admin/profile/edit [edit action]
www.myapp.com/admin/profile/del [delete action]
These URLs are for users with admin permissions.
Users who do NOT have admin permissions have following URLs
www.myapp.com/user/profile
www.myapp.com/user/profile/add
www.myapp.com/user/profile/edit
www.myapp.com/user/profile/del
Routes in Zend 2
// admin routes
'admin' => array(
'type' => 'Literal',
'options' => array(
'route' => '/admin',
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__.'\Controller',
),
),
'may_terminate' => true,
'child_routes' => array(
// Profile
'profile' => array(
'type' => 'Literal',
'options' => array(
'route' => '/profile',
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__ . '\Controller',
'controller' => 'Profile',
'action' => 'index'
)
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:action[/:id]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '\d+'
),
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__ . '\Controller',
'controller' => 'Profile'
)
)
),
)
),
),
),
// user routes
'admin' => array(
'type' => 'Literal',
'options' => array(
'route' => '/user',
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__.'\Controller',
),
),
'may_terminate' => true,
'child_routes' => array(
// Profile
'profile' => array(
'type' => 'Literal',
'options' => array(
'route' => '/profile',
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__ . '\Controller',
'controller' => 'Profile',
'action' => 'clientIndex'
)
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:action[/:id]]',
'constraints' => array(
'action' => 'client[a-zA-Z][a-zA-Z0-9_-]*', <----- look here
'id' => '\d+'
),
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__ . '\Controller',
'controller' => 'Profile'
)
)
),
)
),
),
),
What I want to have is that if user access url: www.myapp.com/admin/profile/add
Application run controller Profile and action addAction
If user access url: www.myapp.com/user/profile/add
Application run controller Profile and action userAddAction
So I want to add prefix 'user' to every action when user routes are used.
I have tried:
'options' => array(
...
'defaults' => array(
'__NAMESPACE__' => __NAMESPACE__ . '\Controller',
'controller' => 'Profile',
'action' => 'user[:action]' <--- look here
)
)
But of course it doesn't work.
I know I could define static routes, but I would like to do it with Segment routes type
There is no need to change the route. Route definitions are there to be matched by the URL, so the application is able to execute the correct controller action.
So by defining 'action' => 'client[a-zA-Z][a-zA-Z0-9_-]*' you are saying that the [:action] part of the route needs to match on this pattern, which would only happen if you browsed to www.myapp.com/admin/profile/clientadd etc.
To resolve your problem you can split your child routes so you have a route per action.
This example shows for the user route, however you can copy this and add them as children of the /admin/profile route also (changing the action value point addAction rather than clientAddAction etc).
// user routes
'user' => [
// same as before
'child_routes' => [
'profile' => [
// same as before
'child_routes' => [
'add' => [
'type' => 'literal',
'options' => [
'route' => '/add'
'defaults' => [
// no need for controller value as is
// inherited from the 'profile' parent route
'action' => 'clientAddAction'
],
],
],
'edit' => [
'type' => 'segment',
'options' => [
'route' => '/edit/:id',
'defaults' => [
'action' => 'clientEditAction',
]
],
],
'del' => [
'type' => 'segment',
'options' => [
'route' => '/del/:id',
'defaults' => [
'action' => 'clientDeleteAction',
]
],
],
],
],
],
];
The only change you would need to make is when you render a URL within the view.
$this->url('/users/profile/default, ['action'=>'add']);
$this->url('/users/profile/default, ['action'=>'edit', 'id' => 123]);
Would become.
$this->url('/users/profile/add');
$this->url('/users/profile/edit, ['id' => 123]);
this is a part of my file:
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '[:controller[/:action]][/:param1]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*'
),
'defaults' => array(
'action' => 'index',
'__NAMESPACE__' => 'Application\Controller',
'param1' => 'tralala'
)
)
)
)
So, instead of param1, I want to define an array, How can I do that ? When i set the keys in the array:
$this->redirect()->toRoute(null, array(
'controller' => 'user',
'action' => 'confirm',
'param1' => array(
'email'=>$request->getPost('mail'),
'name'=>$request->getPost('name')
)
));
and accessing it :
$params = $this->params()->fromRoute('param1');
var_dump($params); exit();
Obviously my code does not work. It is possible to set an array in the route, or I'm asking stupid thing s here ? thx
I actually have 2 modules (Application and Admin) in my ZF2 application and I want a url routing like in ZF1. I currently have the following route:
'router' => array
(
'routes' => array
(
'admin' => array
(
'type' => 'Segment',
'options' => array
(
'route' => 'admin/[:controller[/:action]]',
'constraints' => array
(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array
(
'__NAMESPACE__' => 'Admin\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array
(
'wildcard' => array
(
'type' => 'Wildcard'
)
)
),
),
),
So it will match "/admin", "/admin/controller", "/admin/controller/action" but not "/controller/action".
Now I need a route to the Application module. The problem is that if I simply use a route like that for the module Application, this new route would match "/admin/controller" as controller = "admin" and action = "controller".
I also tried the following regex route in the application:
'application' => array
(
'type' => 'Regex',
'options' => array
(
'regex' => '/(?<controller>^(?!(admin)$)[a-zA-Z][a-zA-Z0-9_-]*)?' .
'(/[a-zA-Z][a-zA-Z0-9_-]*)?',
'spec' => '/%controller%/%action%',
/*'constraints' => array
(
//The controller cannot be "admin"
'controller' => '^(?!(admin)$)[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),*/
'defaults' => array
(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array
(
'wildcard' => array
(
'type' => 'Wildcard'
)
)
),
But it's not getting the variables "controller" and "action".
Does anyone have a suggestion of how to solve that?
mind the route order: routes are handled using a LIFO stack, so what comes last in the array comes first when matching request urls.
this means that you always have to define the most generic routes first to prevent them from matching similar but more specific ones.
using the following order shouldn't need any constraint on the controller parameter, because anything starting with /admin will be matched first
'route1' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'defaults' => array (
'controller' => 'controller',
'action' => 'index',
),
),
),
'route2' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin[/:controller[/:action]]',
'defaults' => array (
'controller' => 'admin-controller',
'action' => 'index',
),
),
),
furthermore, you can always specify excplicitly routes priority using the priority property (which should not be defined under the options array, but in the topmost array of the route), so the following code is equivalent to the previous example:
'route2' => array(
'type' => 'Segment',
'options' => array(
'route' => '/admin[/:controller[/:action]]',
'defaults' => array (
'controller' => 'admin-controller',
'action' => 'index',
),
),
),
'route1' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller[/:action]]',
'defaults' => array (
'controller' => 'controller',
'action' => 'index',
),
),
'priority' => -1,
),
Let's take the example routing config from the documentation (slightly modified):
return array(
'router' => array(
'routes' => array(
'home' => array(
'type' => 'literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\IndexController',
'action' => 'index'
)
)
),
'blog' => array(
'type' => 'literal',
'options' => array(
'route' => '/blog',
'defaults' => array(
'controller' => 'Applicaton\Controller\BlogController',
'action' => 'index'
),
),
'may_terminate' => true,
'child_routes' => array(
'rss' => array(
'type' => 'literal',
'options' => array(
'route' => '/rss',
'defaults' => array(
'action' => 'rss'
)
)
)
)
// ... other child routes ...
)
)
)
);
I want to automatically do a redirect to /blog/rss whenever /blog is called.
Right now I have to redirect from within the index-action of BlogController. I wonder if there is a way to let ZF2 handle the redirect without writing additional code in the action?
how is it possible to match url like www.mydomain.com/en/aboutus to
controller -> index
action -> aboutus
lang -> en
in zf2 module routing config ?
in zf1 we fix that by something like this
$route = new Zend_Controller_Router_Route(
'/contact/:lang',
array(
'module' => 'default',
'controller' => 'contact',
'action' => 'index'
)
);
but the aproeach is something else
we want first determine what the language is in url then look into what controller or action user is requesting
zf2 has hirachy support in routers so you can build your routes like a tree
for your situation you have to create a parent route that match lang in url for example
www.mydomain.com/en or www.mydomain.com/fa or www.mydomain.com/de or ....
then in it children write route for others
for code example :
'langroute' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:lang]',
'defaults' => array(
'lang' => 'en',
),
'constraints' => array(
'lang' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
),
'may_terminate' => true,
'child_routes' => array(
'home' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'index',
),
),
),
// The following is a route to simplify getting started creating
// new controllers and actions without needing to create a new
// module. Simply drop new controllers in, and you can access them
// using the path /application/:controller/:action
'aboutus' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/aboutus',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'aboutus',
),
),
),
),
as you can see the langrout match the en de fa or ... lang text
then the childern route check for inner page
in this example the url www.mydomain.com/en/ match the lang en and the route home
please add this code in your modules module.config.php
return array(
'router' => array(
'routes' => array(
// The following is a route to simplify getting started creating
// new controllers and actions without needing to create a new
// module. Simply drop new controllers in, and you can access them
// using the path /Module_Name/:controller/:lang/:action
'your_route_name_here' => array(
'type' => 'Literal',
'options' => array(
'route' => '/',
'defaults' => array(
'__NAMESPACE__' => 'Module_Name\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '/[:controller][/:lang][/:action]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'lang' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'Index',
'lang' => 'en',
'action' => 'index',
),
),
),
),
),
),
),
);