Zend Framework routing - zend-framework

I'm trying to setup some routes for my ZF app but not getting too far. I have a controller 'WebServiceController', it has an index action and a lookupTransaction action. I want to use routes like this:
ws/
ws/lookupTransaction
Ideally I'd like anything with a 'ws/' prefix to go to the WebServiceController and match the action name. I'm not sure how to do that yet but I am trying to get each route working so I added these two routes:
<?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
function _initRoutes()
{
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->addRoute('ws', new Zend_Controller_Router_Route('ws/', array(
'controller' => 'web-service',
'action' => 'index',
)));
$router->addRoute('ws/lookupTransaction', new Zend_Controller_Router_Route('ws/lookupTransaction', array(
'controller' => 'web-service',
'action' => 'lookup-transaction',
)));
}
}
The first one works as expected but the second one doesn't, I just get 'Application Error'. What am I doing wrong? Just out of interest, if I remove my two routes and try and go to:
web-service/lookup-transaction
I still get the same error!
Solved
Here is how I can make it work with camel cased action name and camel cased URL.
$router->addRoute('ws', new Zend_Controller_Router_Route('ws/:action', array(
'controller' => 'web-service',
'action' => 'index',
)));
$router->addRoute('ws-lookupTransaction', new Zend_Controller_Router_Route('ws/lookupTransaction', array(
'controller' => 'web-service',
'action' => 'lookup-transaction',
)));
Thanks
Ziad

Try just this one route as a solution to both problems:
$router->addRoute('ws', new Zend_Controller_Router_Route('ws/:action', array(
'controller' => 'web-service',
'action' => 'index',
)));
the action parameter then serves as a default, so if no action is specified in the URL, index will be used. Otherwise it will route to the action in the URL. So example.com/ws/lookupTransaction will go to lookuptransactionAction() in your controller.
If this still gives you an error, post the error message so we can see what the problem is.

The router actually transforms URLs to lowercase. So the correct URL should be all lowercase dash separated words. Also I'm not sure if it's possible to use slash in route name (the first parameter of addRoute()).

Related

Zend Framework: Router

That is my two routers:
->addRoute('viewTextMaterial', new Zend_Controller_Router_Route(':mCat/:mCatSub/:mId/:mTitle', array('controller' => 'index', 'action' => 'viewtextmaterial')))
->addRoute('viewNews', new Zend_Controller_Router_Route(':nCat/:nId/:nTitle/:page', array('controller' => 'index', 'action' => 'viewnews')))
In index.phtml file I add this:
Test
Exp. for viewnews URL:
some text
But why, when I click a href, it redirect me to 'viewnews'?
In my experience(which is not very great :) )
I think when you use the colon in front of a name, when you are defining a router
i.e like
'/:mCat/:mCatSub/:mId/:mTitle',
array(
'controller' => 'index',
'action' => 'viewtextmaterial'
)
What you are telling the router to do is to route any url, which follows the above format('/:mCat/:mCatSub/:mId/:mTitle'), to be routed to the controller/action you mentioned there. eg.
someController/action/x/y
or
anoCont/act/a/b
would be routed to the same controller/action.
So in your case what you are doing is you are defining two routers with same options(which creates ambiguity), and by default the second defined route is used(Bottom to top matching).
you can use something like this
'/test/:mCatSub/:mId/:mTitle',
array(
'controller' => 'index',
'action' => 'viewtextmaterial'
)
so anything that starts with 'test' as controller(in the url) would now be routed to your desired controller/view.
Hope it works.. :) (If it doesn't please enlighten me :) )

Zend Routing problems

I've read all posts about routing and Zend Documentation but I still can't solve this issue.
I have a multi-language application with two modules: default and admin. The language selection is working fine (in a Controller routeShutdown Plugin), but I have some problems configuring the router:
I want to have these URL working:
/
/controller
/controller/action
/action (default controller)
/controller/param (default action)
/admin
/admin/admin-controller
/admin/admin-controller/action
and using the language selector it would be:
/en
/en/controller
/en/controller/action
/en/action (default controller)
/en/controller/param (default action)
/en/admin/admin-controller
/en/admin/admin-controller/action
I added this to my bootstap file (index.php):
$frontController = Zend_Controller_Front::getInstance();
$router = $frontController->getRouter();
$router->removeDefaultRoutes();
$router->addRoute('langmodcontrolleraction',
new Zend_Controller_Router_Route('/:lang/:module/:controller/:action',
array('lang' => ':lang'))
);
$router->addRoute('langmodcontroller',
new Zend_Controller_Router_Route('/:lang/:module/:controller',
array('lang' => ':lang',
'action' => 'index'))
);
$router->addRoute('langmod',
new Zend_Controller_Router_Route('/:lang/:module',
array('lang' => ':lang',
'action' => 'index',
'controller' => 'index'))
);
$router->addRoute('lang',
new Zend_Controller_Router_Route('/:lang',
array('lang' => ':lang',
'action' => 'index',
'controller' => 'index',
'module' => 'default'))
);
$frontController->setControllerDirectory(array(
'default'=>BASE_PATH.'app/modules/default/controllers',
'admin'=>BASE_PATH.'app/modules/admin/controllers'));
In order to check how the router is parsing the URL, I added a var_dump to the routeShutdown plugin:
Entering to /en, I get:
array
'lang' => string 'en' (length=2)
'action' => string 'index' (length=5)
'controller' => string 'index' (length=5)
'module' => string 'default' (length=7)
which is OK. But when I enter to /en/controller1 I get:
array
'lang' => string 'en' (length=2)
'module' => string 'controller1' (length=8)
'action' => string 'index' (length=5)
'controller' => string 'index' (length=5)
It is setting module to "controller1". How can I tell the router to set the default value to the module? And for an URL like /en/controller/param? (setting module and action to default)
I'm afraid you're going to need to rethink your URL scheme a little, or change the way your routes are setup, as you've hit two limitations of the way ZF's routing works.
The first is that the router has no knowledge of what is or isn't a valid module, controller or action; all it does is match the strings in the URL to variables in the route. It does this by checking each route in succession, in reverse order, until it finds a match. When you hit /en/controller, it first checks your /:lang route, which won't match. It then checks /:lang/:module, which will match, because /:lang/:module will match /anything/anything unless you tell it otherwise.
With that in mind you won't be able to have both:
/en/controller
/en/action
unless you set some restrictions, as a URL like /en/foo will always be matched by whichever of the two you define last.
If you have a fairly small number of actions/controllers that don't often change, the simplest way around this is to hardcode in some possible values for the 2nd of the two routes, e.g.:
$router->addRoute('langmod', new Zend_Controller_Router_Route(
'/:lang/:module',
array(
'lang' => ':lang',
'action' => 'index',
'controller' => 'index'
),
array(
'module' => '(foo|bar|something)'
)
));
replace foo, bar etc. with valid module names. Now when you hit /en/controller1 it won't match this route because controller1 doesn't match the regexp pattern defined for the :module variable. You would then need a separate /:lang/:controller route (or possibly /:lang/:controller/:action) for it to match instead.
You asked how you set a default value for some of the variables. You are actually already doing this with the action in a few of your routes, but for controller/module won't quite work in the way you are hoping. If we take your langmodcontroller route and change it to this:
$router->addRoute('langmodcontroller',new Zend_Controller_Router_Route(
'/:lang/:module/:controller',
array(
'lang' => ':lang',
'controller' => 'index'
'action' => 'index'
)
));
there's now a default value for the controller variable. If we pretend for a second that this was the only route, a request for /en/blog would now get matched by this and set the request params to lang = en, module = blog, controller = index, action = index. /en/blog/index/foo would also match this route, and would give you module = blog, controller = index, action = foo. But note that even though controller = index you still need that in the URL. So limitation number two is that you always need the variable in the URL (even if it is set to your default) as long as you have something after it that isn't the default.
With these limitations in mind I'd suggest you go with something like this (defined in this order):
/:lang/:controller/:action/ (with 'index' defaults for controller and action)
/:lang/:action (with 'action' restricted to some predefined values)
/:lang/admin/:controller/:action (with 'admin' as a string in the URL, and :module set to 'admin' as the default)
This would give you URLs like this:
/en
/en/controller
/en/controller/action
/en/action
/en/controller/param
/en/admin/controller
/en/admin/controller/action
which is pretty much what you are after.
The routing in ZF is very powerful, you just need to know its quirks.

Pretty Zend Framework urls

I would like to have my urls like this:
/index
/contact
/articles
/articles/selection
...
Instead of:
/index/index
/index/contact
/articles/index
/articles/selection
...
Basically I have only one controller. Which solution is the best to perform this? (controllers and redirections, ZF routing, url rewriting, something else?)
Have a look at the documentation. The behaviour you want is configured as default in the default router:
http://framework.zend.com/manual/en/zend.controller.router.html
if the first param do not maps a module name, it will search for a controller and if this fails too, it is looking for an action in your IndexController.
Did you tried calling your url's like you want to?
What happens if you navigate to /index? Should be the same like /index/index
use zend routing :
$router = Zend_Controller_Front::getInstance()->getRouter();
$route_index = new Zend_Controller_Router_Route(':action', array(
'module' => 'default',
'controller' => 'index',
'action' => 'index'
));
$router->addRoute('route_index', $route_index );
$route_articles = new Zend_Controller_Router_Route('articles/:action', array(
'module' => 'default',
'controller' => 'articles',
'action' => 'index'
));
$router->addRoute('route_articles ', $route_articles );

Zend Framework Change parameter in route on the same spot?

I'm not sure how to fix this, or wat is the best way to approach this. Also couldn't find enough information to get me on the right way (could be that my searching sucks..)
Anyway, this is my problem:
I defined a route in my bootstrap file:
protected function _initRoutes()
{
$router = $this->frontController->getRouter();
$router->removeDefaultRoutes();
$router->addRoute(
'delete',
new Zend_Controller_Router_Route('/:controller/:action/:id/',
array('controller' => ':controller',
'action' => ':action',
'id' => ':id',
)
)
);
}
This works perfectly for my update and delete actions.
Now I've added the pagination to the indexpage. The pagination expects the page parameter. Because I haven't set this in my route, it cannot pass it, so my pagination doesn't work (as in switching between results).
I understand this. But what I want is that on the index page the id parameter isn't necessary and replace this with the page parameter.
Trying another route replacing id with page didn't work.
Is there a good way to solve this in the bootstrap or is it the best way to check for the action, and depending on the action, index or update/delete, define the route. The best place would than be a plugin?
Any advice or tips are greatly appreciated!
While working on another aspect of the application I came back to the same problem. I solved it, by specifying the routes much more.
First I deleted the $router->removeDefaultRoutes(); rule.
And then instead of (which didn't work):
$router->addRoute(
'crud',
new Zend_Controller_Router_Route('/:controller/:action/:id', array('controller' => ':controller', 'action' => ':action', 'id' => ':id'))
);
$router->addRoute(
'pagination',
new Zend_Controller_Router_Route('/:controller/:action/:page', array('controller' => ':controller', 'action' => ':action', 'page' => ':page'))
);
I now use this:
$router->addRoute(
'crud',
new Zend_Controller_Router_Route('/:controller/:action/:id', array('controller' => ':controller', 'action' => ':action', 'id' => ':id'))
);
$router->addRoute(
'pagination',
new Zend_Controller_Router_Route('/:controller/index/:page', array('controller' => ':controller', 'action' => 'index', 'page' => ':page'))
);

Using Zend_Controller_Router_Route to create friendly URLs for the actions in IndexController

In my IndexController, I currently have indexAction (homepage), loginAction and logoutAction. I'm trying to remove "/index/" from the URL to get domain.com/login instead of domain.com/index/login.
What is the cleanest way to achieve this? Is there a RegEx we can use? I don't ever want /index/ in the URL.
My current solution, which I believe can be improved upon, is below. Also, what does the first parameter in addRoute() do?
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
protected function _initViewHelpers()
{
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$router->addRoute('login',
new Zend_Controller_Router_Route('login/*', array(
'controller' => 'index',
'action' => 'login'
))
);
$router->addRoute('logout',
new Zend_Controller_Router_Route('logout/*', array(
'controller' => 'index',
'action' => 'logout'
))
);
}
}
There is nothing to impove, you have to create route for every action. This will allow you to change route defaults (module/controller/action) without modifying your code.
First parameter is the route name, which you have to use with url() helper in your views:
Login
Update. You can use such route, if you want only one route without "index" in url:
$router->addRoute('default',
new Zend_Controller_Router_Route(':action/*', array(
'controller' => 'index',
))
);