zend framework: url with special characters not matching with defined route - zend-framework

I have defined a simple route which also accepts query parameters but sometimes some browser encode the query params and it stops working.
'searchResultPage' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/search',
'defaults' => array(
'controller' => 'Application\Controller\Index',
'action' => 'searchResultPage',
),
),
),
When I type mydomain.com/search?q=test it is working but when i type mydomain.com/search%3Fq=test (some browser specially mobile browsers encode the query params) it redirects me to 404 error page.

Related

Zf2 : Controller forwarding/calling generate 404 Error

I am implementing separate auth solution for two different modules described in another question by me.
Zend framework 2 : Add different authentication adapter for two different modules
Now in AuthListener file I write code for forward/call to an different controller/action if authentication failed. That is
$result = $this->adapter->authenticate();
if (!$result->isValid()) {
$response = $event->getResponse();
// Set some response content
$response->setStatusCode(401);
$routeMatch = $event->getRouteMatch();
$routeMatch->setParam('controller', 'First\Controller\Error');
$routeMatch->setParam('action', 'Auth');
}
Now I am getting 404 error - "The requested controller was unable to dispatch the request". First I think I do not added route for Error/Auth, but then I verified it got 404 for all other controller/action too. All are directly accessible through their respective route. But forwarding resulting in 404 error. One important thing - I sending authentication request through phpunit to make unit test cases.
UPDATE : route details :
'routes' => array(
'rest' => array(
'type' => 'Zend\Mvc\Router\Http\Segment',
'options' => array(
'route' => '/rest[/:id]',
'constraints' => array(
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'First\Controller\Index'
),
),
),
'error' => array(
'type' => 'segment',
'options' => array(
'route' => '/rest-error/[/:action][/:id]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[0-9]+',
),
'defaults' => array(
'controller' => 'First\Controller\Error',
'action' => 'auth',
),
),
)
),
'controllers' => array(
'invokables' => array(
'First\Controller\Auth' => 'First\Controller\AuthController',
'First\Controller\Error' => 'First\Controller\ErrorController'
),
),
Module.php
$listener = $serviceManager->get('First\Service\AuthListener');
$listener->setAdapter($serviceManager->get('Rest\Service\BasicAuthAdapter'));
$eventManager->getSharedManager()->attach('First', 'dispatch', $listener, 100);
I also tried to use forward instead of above solutio, But that gives error for circular forward Circular forwarding detected: greater than 10 nested forwards. I think event called when forward called.
try to call your action like that :
$routeMatch->setParam('action', 'auth');
I think the problem might occure because you are listening to MvcEvent::EVENT_DISPATCH. In your listener you set new controller and action variables for RouteMatch but since you are already passed the route event changing those parameters will not have any effect.
You should listen to MvcEvent::EVENT_ROUTE instead and then it will probably work.

Zend routing (default controller to handle all url)

At first sorry for my poor English.
I want to handle all requests which do not match with my routes to CustomPageController.
I am trying to configure my module.config.php like this:
'defaults' => array(
'type' => 'Zend\Mvc\Router\Http\Literal',
'options' => array(
'route' => '/*', // or 'route' => '/user*' for example, to handling www.site.com/user4 (just as example)
'defaults' => array(
'controller' => 'custom_page',
'action' => 'index',
),
),
),
To handle all queries that do not match with routes must redirect to my last "defaults" route. But it is not working.
You can use your ErrorController as an alternative for this. If the controller name is not found then you get the error code 500. You can then do whatever you want to do on that controller (re-route to your CustomPageController)

a link pass multiple parameter in zend framework

hi i am new in zend framework 2.2.0. i want to create the a link that go to delete page right now i am passing only id in the url so i want to pass another id in it.
Add to Trash
right now in this link message id is passing i also want to pass one more id named "did" in this link
Add to Trash
how can i get this ?
thanks in advance
You should use url view helper's third argument ($options) to pass your variables in the query string. Example:
$route = 'message';
$param = array('action' => 'delete');
$opts = array(
'query' => array(
'id' => $message->message_id,
'did' => $message->deliver_id
)
);
$this->url($route, $params, $opts);
You have to add "did" to your message route like this:
'router' => array(
'routes' => array(
'message' => array(
'type' => 'segment',
'options' => array(
'route' => '/:action/:id[/:did]',
'constraints' => array(
'action' => '[a-zA-Z][a-zA-Z0-9_-]+',
'id' => '[0-9]+',
'did' => '[0-9]+',
),
'defaults' => array(
'controller' => 'Application\Controller\Index',
),
),
),
),
),
echo $this->url('message',array('action'=>'delete', 'id' => $message->message_id,'did'=>$message->deliver_id);
// output: /delete/1/2

same controller name in different modules in zf2

I just disvovered today that zf2 doesn't realy like when 2 controllers have the same name even if they are not in the same module.
However, I need to be able to call
localhost/users/types
and
localhost/messages/types
For the moment, my two controllers have the same names.
I also discovered that whatever the name of the module is, I always get the result of messages/types, even with localhost/nonexistingmodule/types oO
Here is what my module.config.php looks like :
return array(
'controllers' => array(
'invokales' => array(
'messages' => 'Messages\Controller\MessagesController,
'messages' => 'Messages\Controller\TypesController,
),
),
'di' => array(
'instance' => array(
'alias' = array(),
),
),
'router' => array(
'routes => array(
'restful' => array(
'type' => 'Zend\Mvc\Router\Http\Segment'
'options' => array(
'route' => '/Messages/:controller[.:formatter][/:id],
'constraints' => array(
'module' => '[a-zA-Z][a-zA-Z0-9_-]*',
'controller' => '[a-zA-Z][a-zA-Z0-9_-]*',
'formater' => '[a-zA-Z][a-zA-Z0-9_-]*',
'id' => '[a-zA-Z0-9_-]*',
),
'defaults' => array(
'module' => 'Messages',
),
),
),
),
),
'view_manager' => array( ... ),
);
I have tried to set 'module' => 'Messages' in constraints (we never know :p) but I had a 404 error.
The module.config.php of the Tasks module is the same but for tasks.
I originaly had aliases but I removed them after I read somewhere this was not very recomanded.
One more thing, this is a REST API, all my controllers extends AbstractRestfulController (in case this is important)
Anyone has an idea of how to make my 2 url to work?
Thanks :)
Aliases for invokables or services and anything else should be unique. If they are not unique they may be overwritten by another module in the order the modules themselfes are loaded. That means: when setting up invokables or any sorts of aliases, make sure that the aliases are unique and meaningful. Personally i name my Controllers like this:
'invokables' => array(
'mymodule-controller-controllername' => 'Mymodule\Controller\ControllernameController'
)
Same with Services or any other sorts of aliases
'services' => array(
'mymodule-service-servicename' => 'Mymodule\Service\Classname'
)
The Documentation follows a Namespace-styled syntax like...
'invokables' => array(
'Mymodule\Controller\Controllername' => 'Mymodule\Controller\ControllernameController'
)
...which personally i find totally confusing, as it resembles a Namespace way too much and doesn't really auto-imply that it is just an alias / key
Now your comments-question i do not understand. You want to match one route to two different controllers? That would be impossible and senseless.
Answer Update with routing config
As for routing configuration you have several possible ways. Personally i put lots of effort into building up literal routes, since they are the fastest, but also require a lot of manual attention. Alternatively there is segment routes which inhibit a little more magic to them. I will cover the literal approach for you:
Module Messages
'controllers' => array(
'invokables' => array(
'messages-controller-index' => 'Messages\Controller\IndexController',
)
),
'router' => array(
'routes' => array(
'messages' => array(
'type' => 'literal',
'options' => array(
'route' => '/messages',
'defaults' => array(
'controller' => 'messages-controller-index',
'action' => 'index'
)
),
'may_terminate' => true,
'child_routes' => array(
'types' => array(
'type' => 'literal',
'options' => array(
'route' => '/types',
'defaults' => array(
'action' => 'types'
)
)
)
)
)
)
)
Module Tasks
'controllers' => array(
'invokables' => array(
'tasks-controller-index' => 'Tasks\Controller\IndexController',
)
),
'router' => array(
'routes' => array(
'tasks' => array(
'type' => 'literal',
'options' => array(
'route' => '/tasks',
'defaults' => array(
'controller' => 'tasks-controller-index',
'action' => 'index'
)
),
'may_terminate' => true,
'child_routes' => array(
'types' => array(
'type' => 'literal',
'options' => array(
'route' => '/types',
'defaults' => array(
'action' => 'types'
)
)
)
)
)
)
)
So what's happening there is:
if route is /messages if routes to controller-alias messages-controller-index with indexAction()
if route is /messages/types it stays at controller-alias messages-controller-index but goes to typesAction()
if route is /tasks if routes to controller-alias tasks-controller-index with indexAction()
if route is /tasks/types it stays at controller-alias tasks-controller-index but goes to typesAction()
You could obviously change controller aliases and meanings behind that. If you'd want to add an ID for a route like /messages/types/1 you'd build a child-route to the types-route that is of type segment and check for an [:id] parameter whose constraints should be numeric :) Check the official ZF2 Manual for more information, i'm lazy now :P
tl;dr: Make sure you have a __NAMESPACE__ default in your route definition, and then make sure all your service names are prefixed with it. Usually, the value will match your module namespace.
For the longer explanation:
I'm going to be blunt: it's a really bad practice to have a dynamic segment in your route that maps to the controller (:controller in your example). The reason is that if somebody discovers this, they can do controller injection, and request a controller that should not be routed by this particular route.
Additionally, the practice can easily lead to collisions, particularly if you omit a __NAMESPACE__ default in your route configuration -- which, based on the question, you've already discovered.

Zend 2 router setting

Im very mew to ZF2, and cant figure out how to set the global router.
I know how to set on module level:
http://packages.zendframework.com/docs/latest/manual/en/user-guide/routing-and-controllers.html says:
The mapping of a URL to a particular action is done using routes that
are defined in the module’s module.config.php file. We will add a route
for our album actions. This is the updated config file with the new
code commented.
// The following section is new and should be added to your file
'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',
),
),
),
),
),
Is there a way to config a default behaviour for the whole application? Or i have to confing in each module?
config/application.config.php would be a logical place for it. Is it somewhere documented?
What your ZF2 module defines in getConfig() gets merged with all the other module configs and eventually replaced by modules loaded afer it if some config keys collide. Thus your getConfig() already affects the entire application and its scope is not limited to your module only.