I don't know how can I explain my problem. I'm trying to get JSON response from one of my module that extend abstractrestfulcontroler. I have following module configuration
File: module.config.php
return array(
'controllers' => array(
'invokables' => array(
'TfwCommunication\\Controller\\TfwCommunication' => 'TfwCommunication\\Controller\\TfwCommunicationController',
'TfwCommunication\\Controller\\TfwChat' => 'TfwCommunication\\Controller\\TfwChatController',
'TfwCommunication\\Controller\\TfwContacts' => 'TfwCommunication\\Controller\\TfwContactsController',
'TfwCommunication\\Controller\\TfwMessage' => 'TfwCommunication\\Controller\\TfwMessageController',
'TfwCommunication\\Controller\\TfwUserMessageTemplates' => 'TfwCommunication\\Controller\\TfwUserMessageTemplatesController',
'TfwCommunicationControllerTfwUserMessageTemplates' => 'TfwCommunication\\Controller\\TfwUserMessageTemplatesController',
),
),
'router' => array(
'routes' => array(
'communication' => array(
'type' => 'Segment',
'options' => array(
'route' => '/communication',
'constraints' => array(
#'id' => '[0-9]+', # '[a-zA-Z][a-zA-Z0-9_-]*',
#'action'=>'[a-z][a-z0-9]*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwCommunication',
'action' => 'index',
#'id'=>'update',
#'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'actions'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/[:action[/]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwCommunication',
'action' => 'index',
),
),
),
'message' => array(
'type' => 'Segment',
'options' => array(
'route' => '/message',
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwMessage',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'read'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/[:id]',
'constraints' => array(
'id' => '[0-9]*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwMessage',
'action' => 'read',
),
),
),
'actions'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/[:action[/[:id]]]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwMessage',
'action' => 'index',
),
),
),
'json-request-by-child-route'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/json-request-by-child-route[/:id]',
'constraints' => array(
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunicationControllerTfwUserMessageTemplates',
),
),
),
),
),
),
),
'user-defined-templates'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/communication/message/user-defined-templates[/:id]',
'constraints' => array(
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwUserMessageTemplates',
),
),
),
'user-defined-templates-direct-link'=>array(
'type' => 'Segment',
'options' => array(
'route' => '/user-defined-templates-direct-link[/:id]',
'constraints' => array(
'id' => '.*',
),
'defaults' => array(
'controller' => 'TfwCommunication\\Controller\\TfwUserMessageTemplates',
),
),
),
),
),
'view_manager' => array(
'template_path_stack' => array(
'tfwcommunication' => __DIR__ . DS.'..'.DS.'view',
),
'strategies' => array(
'ViewJsonStrategy',
),
),
);
Now following link is working - tfw.com.bd/communication/message/user-defined-templates/ OR tfw.com.bd/user-defined-templates-direct-link/
But following link will not work as expected (it says 404 controller not found) - tfw.com.bd/communication/message/json-request-by-child-route
Here tfw.com.bd indicating localhost.
Please note, I'm expected output as JSON format.
Also noted that, all I use here same controller. In some link/route it didn't work. I can't figure out the reason.
Can any ZF2 expert here who can explain the real reason behind the behavior.
Thanks
Finally I got this answer by myself. The above routing configuration didn't works due to default "action" define as "index". Zend seek "action" parameter, if found then it load that action. If not found it return "notFoundAction". So, in child route of above router defines "action" parameter. So, Zend din't go further when either it goes default "indexAction" or goes "notFoundAction".
Footnote, you need to avoid action parameter to get "JsonStrategy" works as expected. If you can't avoid action parameter in your router you can fix it by overloading "onDispatch" method of "AbstractRestfulController" controller.
Here is my code that works for me -
public function onDispatch(MvcEvent $e){
$routeMatch = $e->getRouteMatch();
if (! $routeMatch) {
/**
* #todo Determine requirements for when route match is missing.
* Potentially allow pulling directly from request metadata?
*/
throw new Exception\DomainException(
'Missing route matches; unsure how to retrieve action');
}
$request = $e->getRequest();
// Was an "action" requested?
#die('get_class($routeMatch): '.get_class($routeMatch).' #'.__LINE__.': '.__FILE__);
$action = $routeMatch->getParam('action', false);
if ($action) {
// Handle arbitrary methods, ending in Action
$method = static::getMethodFromAction($action);
if (! method_exists($this, $method)) {
if($method=='indexAction'){
$routeMatch->setParam('action', false);
return parent::onDispatch($e);
}
$method = 'notFoundAction';
}
$return = $this->$method();
$e->setResult($return);
return $return;
}
return parent::onDispatch($e);
}
Related
I have created a controller called "ActividadesPlanificadasController.php" and I have defined in my module.config the next routing but it is not work.
'publico/peticiones-incidencias-planificadas/actividades-planificadas' => array(
'type' => 'Literal',
'options' => array(
'route' => 'publico/peticiones-incidencias-planificadas/actividades-planificadas',
'defaults' => array(
'__NAMESPACE__' => 'Privado\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
//'route' => '/[:controller[/:action[/:id]]]',
'route' => '/[:controller[/:action][/:id/:system]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
'system' => '[a-zA-Z][a-zA-Z0-9_-]*'
//'system' => '[0-9]*'
),
'defaults' => array(
),
),
),
),
),
These are my controllers ...
'controllers' => array(
'invokables' => array(
'Publico\Controller\Index' => Controller\IndexController::class,
'Publico\Controller\Login' => Controller\LoginController::class,
'Publico\Controller\NoAccess' => Controller\NoAccessController::class,
'Publico\Controller\ActividadesPlanificadas' => Controller\ActividadesPlanificadasController::class
),
),
Because I want to access to my controller with the next url: http://gnsys.local/publico/peticiones-incidencias-planificadas/actividades-planificadas
And I've got the next error ...
A 404 error occurred
Page not found.
The requested controller could not be mapped to an existing controller class.
Controller:
Publico\Controller\PeticionesIncidenciasPlanificadas(resolves to invalid controller class or alias: Publico\Controller\PeticionesIncidenciasPlanificadas)
No Exception available
What am I doing wrong?
Edit 1:
I have updated my module.config and it works with the route: http://gnsys.local/publico/actividades-planificadas
module.config:
'publico/actividades-planificadas' => array(
'type' => 'Literal',
'options' => array(
'route' => 'publico/actividades-planificadas',
'defaults' => array(
'__NAMESPACE__' => 'Publico\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
//'route' => '/[:controller[/:action[/:id]]]',
'route' => '/[:controller[/:action][/:id/:system]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
'system' => '[a-zA-Z][a-zA-Z0-9_-]*'
//'system' => '[0-9]*'
),
'defaults' => array(
),
),
),
),
),
'controllers' => array(
'invokables' => array(
'Publico\Controller\Index' => Controller\IndexController::class,
'Publico\Controller\Login' => Controller\LoginController::class,
'Publico\Controller\NoAccess' => Controller\NoAccessController::class,
'Publico\Controller\ActividadesPlanificadas' => Controller\ActividadesPlanificadasController::class
),
),
But I want that my route to access to ActividadesPlanificadasController would be: http://gnsys.local/publico/peticiones-incidencias-actividades/actividades-planificadas
If I change my module.config to ...
'publico/peticiones-incidencias-planificadas/actividades-planificadas' => array(
'type' => 'Literal',
'options' => array(
'route' => 'publico/peticiones-incidencias-planificadas/actividades-planificadas',
'defaults' => array(
'__NAMESPACE__' => 'Publico\Controller',
'controller' => 'Index',
'action' => 'index',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
//'route' => '/[:controller[/:action[/:id]]]',
'route' => '/[:controller[/:action][/:id/:system]]',
'constraints' => array(
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]*',
'system' => '[a-zA-Z][a-zA-Z0-9_-]*'
//'system' => '[0-9]*'
),
'defaults' => array(
),
),
),
),
),
I've got the error
A 404 error occurred Page not found.
The requested controller could not be mapped to an existing controller class.
Controller: Publico\Controller\PeticionesIncidenciasPlanificadas(resolves to
invalid controller class or alias:
Publico\Controller\PeticionesIncidenciasPlanificadas)
No Exception available
What am I still doing wrong?
You point to a controller called 'Privado\Controller\Index' but your invokable is called 'Publico\Controller\Index'.
Change the namespace so it corresponds.
Privado -> Publico
or
Publico -> Privado
or add a controller for 'Privado\Controller\Index'
'invokables' => array(
'Privado\Controller\Index' => //your privado controller,
//...other controllers...
)
UPDATE
Make also sure you have an invokable controller class in the correct namespace. So if you register like this:
'invokables' => array(
'Privado\Controller\Index' => 'Privado\Controller\IndexController'
)
You need a controller class in a php file called IndexController.php in the folder Privado - Controller
- Privado
- Controller
- IndexController.php
And the class should have the correct name and namespace constant:
<?php
namespace = Privado\Controller;
class IndexController extends ... {
}
So I'm trying to redirect my code to another action within a controller http://localhost/salesorder/view?id=5509c273f948e7cf068b456a this view action is working fine. But every time the redirect code runs it redirects me to http://localhost/salesorder?id=5509c273f948e7cf068b456a
I am now clueless what is did I do wrong.
$params = ['controller' => 'SalesOrder',
'action' => 'view',
];
$options = ['query' => ['id' => (string) $orderId]];
return $this->redirect()->toRoute('Salesorder', $params, $options);
My moduleconfig looks like this
'Salesorder' => array(
'type' => 'Literal',
'options' => array(
'route' => '/salesorder',
'defaults' => array(
'__NAMESPACE__' => 'Backend\Controller',
'controller' => 'SalesOrder',
'action' => 'new',
),
),
'may_terminate' => true,
'child_routes' => array(
'default' => array(
'type' => 'Segment',
'options' => array(
'route' => '[/:action]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
),
'defaults' => array(
'action' => 'new'
),
),
),
),
),
Excuse me that I cannot put a comment since I have not enough reputation, but this may lead you to a solution:
First of all fix the toroute function call to this:
return $this->redirect()->toRoute('Salesorder', array('id'=> (string) $orderId));
Then fix the route specification to this:
'Salesorder' => array(
'type' => 'segment',
'options' => array(
'route' => '/MODULE_NAME/SalesOrder/new/:id[/]',
'constraints' => array(
'id' => '[a-zA-Z0-9_-]*'
),
'defaults' => array(
'controller' => 'MODULE\Controller\SalesOrder',
'action' => 'new',
),
),
),
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(
),
),
),
),
),
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!
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.