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]);
Related
This is the error that i am getting. I am learning zf2 from a book but they forget to say where i should put this piece of code (i tried few attempts but none of them wokred.)
This is my module.config.php
<?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(
'route' => '/users',
'defaults' => array(
'__NAMESPACE__' => 'Users\Controller',
'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(),
),
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'users' => __DIR__ . '/../view',
),
),
);
Where should this be ?
'user-manager' => array(
'type' => 'Segment',
'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',
),
),
),
The url is
http://zend2.com/users/user-manager/edit/5
Thank you !
It should be in the 'child_routes' array instead of the default route. which should depending if you want to use it should be on the same level as 'users'
Also in the route the address is written with a uppercase U in User-manager this is case sensative so you should write ur address as http://zend2.com/users/User-manager/edit/5
I am trying to create edit records functionality in my listing page. But i am getting following error when clicking on edit link against record.
A 404 error occurred
Page not found.
The requested URL could not be matched by routing.
No Exception available
My module.config.php file code for edit view is :
'edit' => array(
'type' => 'literal',
'options' => array(
'route' => '/album[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Application\Controller\Album',
'action' => 'edit',
),
),
),
And my Album listing page code for calling edit controller and passing id to is :
<a href="<?php echo $this->url('edit',
array('action'=>'edit', 'id' => $album->id));?>">Edit</a>
and editAction code is :
$id = (int) $this->params()->fromRoute('id', 0);
Please let me know what i m missing. I am new to zend framework.
i think you have to use 'type' => 'segment' have a look on the documentation
<?php
'edit' => array(
'type' => 'segment', /* <--- use segment*/
'options' => array(
'route' => '/album[/][:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Application\Controller\Album',
'action' => 'edit',
),
),
),
Advise regarding the type option is correct, however you will also need the may_terminate option to ensure that the router knows that this route can be matched.
'edit' => 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' => 'Application\Controller\Album',
'action' => 'edit',
),
),
'may_terminate' => true, // Add this line
),
See now my route script in module.config.php is this.
'album' => array(
'type' => 'literal',
'options' => array(
'route' => '/album/',
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Album',
'action' => 'album',
),
),
'may_terminate' => true,
'child_routes' => array(
'add' => array(
'type' => 'Segment',
'options' => array(
'route' => '/album/[:add]',
'constraints' => array(
'add' => '[a-zA-Z0-9_-]+'
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Album',
'action' => 'add',
),
),
),
'edit' => array(
'type' => 'Segment',
'options' => array(
'route' => '/album/[:edit][/:id]',
'constraints' => array(
'edit' => '[a-zA-Z0-9_-]+'
),
'defaults' => array(
'__NAMESPACE__' => 'Application\Controller',
'controller' => 'Album',
'action' => 'edit',
),
),
),
),
),
in this case if i am clicking on any link only the album page displaying not other which i am hitting.
Finally i got solution and now my application is working perfectly....
I just replace above code with :
'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' => 'Application\Controller\Album',
'action' => 'album',
),
),
),
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.
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',
),
),
),
),
),
),
),
);