i am building a web service with zend and i am using modules to separate my api versions. Ex: "applications/modules/v1/controllers", "applications/modules/v2/controllers" have different set of actions and functionality.
I have made "v1" as the default module in "application.ini" file:
resources.modules = ""
resources.frontController.defaultModule = "v1"
resources.frontController.moduleDirectory = APPLICATION_PATH "/modules"
resources.frontController.moduleControllerDirectoryName = "controllers"
I have written the following in my bootstrap file:
$router = $front->getRouter();
$r1 = new Zend_Controller_Router_Route_Regex('api/v1/tags.xml',
array('module' => 'v1', 'controller' => 'tags', 'action' => 'index'));
$router->addRoute('route1', $r1);
Suppose, if this is my url: http://localhost/api/v1/tags.xml
then it belongs to version 1 (v1).
But i dont want to write many routes like this one, so i want to know how can i track the version from the regex url and dynamically determine the api version to be used (1 or 2).
try to use
$r1->addRoute(
'json_request',
new Zend_Controller_Router_Route_Regex(
'([^-]*)/([^-]*)/([^-]*)\.xml',
array(
'controller' => 'index',
'action' => 'index',
'request_type' => 'xml'),
array(
1 => 'module',
2 => 'controller',
3 => 'action'
)
));
Try this:
$r1 = new Zend_Controller_Router_Route_Regex('api/(v.*)/tags.xml',
array('module' => 'v1', 'controller' => 'tags', 'action' => 'index'),
array(1 => 'module')
);
This will automatically overwrite the module param, and should therefor automatically route to the right module. No need to use a plug-in with the preDispatch method anymore.
So far, i tried like this:
$r1 = new Zend_Controller_Router_Route_Regex('api/v(.*)/tags.xml',
array('module' => 'v1', 'controller' => 'tags', 'action' => 'index'),
array(1 => 'version')
);
$router->addRoute('route1', $r1);
And I could get an idea from here:
So now i used a front controller and in preDispatch method, i am setting the module name based on the value i get in the "version" parameter value, like
if($request->getParam('version') == 2 { $request->setModuleName('v2') }
But after changing the version in url to v2, it still goes to the action of controller in v1 module.
Related
In my bootstrap file, I have the following routing chain. The desired behaviour is to send any request through /usa/:controller/:action to the local module.
For instance, when http://{hostname}/usa/index/index is called, the request goes through the local module, index controller, index action.
The problem I am having is adding parameters. For instance, when I request http://{hostname}/usa/index/index/id/5 to try to get the id parameter, I get the following error message:
An Error occurred. Page not found. Exception information: Message: Invalid controller specified (usa) with the following request params:
array (
'controller' => 'usa',
'action' => 'index',
'id' => '5',
'module' => 'default',
)
How can I set up the chain routing in order to still utilize other parameters?
Here is my code in the application bootstrap:
protected function _initRouting(){
$router = Zend_Controller_Front::getInstance()->getRouter(); // Get the main router from the front controller.
$router->addDefaultRoutes(); // Don't forget default routes!
//get default local route (directs to the local module)
$defaultLocalRoute = new Zend_Controller_Router_Route(
'/:controller/:action',
array(
'module' => 'local',
'controller' => 'index',
'action' => 'index'
)
);
$regionRoute = new Zend_Controller_Router_Route(
'/usa/',
array('region' => 'usa')
);
//chain this region route to the default local route that directs to the local module
$fullRegionRoute = $regionRoute->chain($defaultLocalRoute);
//add the full route to the router (ie. hamiltonRoute, atlanticcaRoute)
$regionRouteName = 'usaRoute';
$router->addRoute($regionRouteName, $fullRegionRoute);
}
Adding a * to the end of the $defaultLocalRoute was able to fix this issue for me.
//get default local route (directs to the local module)
$defaultLocalRoute = new Zend_Controller_Router_Route(
'/:controller/:action/*',
array(
'module' => 'local',
'controller' => 'index',
'action' => 'index'
)
);
Now when going to http://{hostname}/usa/product/view/id/5, the request goes to the desired location ->
module: 'local',
controller: 'product',
action: 'view',
params: array('id'=>5)
I'm using Zend, and here is my problem, i have two different urls that i really want to keep like they are.
i want url : "www.urlA.com" to be directed to application/moduleA/indexController/indexAction
and "www.urlB.com" to application/index/index.
In other words, i want Zend_Router to make sure that when i type www.urlA.com/index/login i use the application/moduleA/ Index controller and loginAction().
I want to keep the classic Zend routing, just adding the fact that my module is already specified in the url.
I have the following code int the bootstrap:
protected function _initRouter()
{
$router = Zend_Controller_Front::getInstance()->getRouter();
$route = new Zend_Controller_Router_Route_Hostname(
'www.urlA.com',
array(
'module'=>'moduleA'
)
);
$routeURI = new Zend_Controller_Router_Route();
$router->addRoute('modulea', $route->chain($routeURI));
}
This way with the "urlA" i correctly go to moduleA/index/index but
"urlA/index/login" doesn't work.
Thanks for any help.
I had a similar problem once and I wrote this :
//ADMIN page
$admin = array('module' => 'admin', 'controller' => 'index', 'action' => 'index');
$hostRoute_admin = new Zend_Controller_Router_Route_Hostname('admin.mysite.com', $admin);
//special environement Website
$env = array('module' => 'env', 'controller' => 'index', 'action' => 'index');
$hostRoute_env = new Zend_Controller_Router_Route_Hostname('env.mysite.com', $env);
//Zend classic routing
$plainPathRoute = new Zend_Controller_Router_Route(':controller/:action/*',
array('controller' => 'index', 'action' => 'index'));
//add specific routing
Zend_Controller_Front::getInstance()->getRouter()->addRoute('admin', $hostRoute_admin->chain($plainPathRoute));
Zend_Controller_Front::getInstance()->getRouter()->addRoute('env', $hostRoute_env->chain($plainPathRoute));
I'm currently creating a new version of my website using Zend Framework and I'm stuck with a little problem I've seen in the past.
There are my routes: (a part)
// BLOG -> CATEGORIES
$route = new Zend_Controller_Router_Route(
'blog/categories',
array(
'module' => 'blog',
'controller' => 'categories',
'action' => 'index'
)
);
$router->addRoute('blog-categories', $route);
// BLOG -> CATEGORIES -> LIST ARTICLES (:alias = name of the category)
$route = new Zend_Controller_Router_Route(
'blog/categories/:alias',
array(
'module' => 'blog',
'controller' => 'categories',
'action' => 'list',
'alias' => null
)
);
$router->addRoute('blog-categories-list', $route);
The problem is that: when I go to /blog/categories/, it brings me the list action. What I don't want. I need the index.
Is there a way to fix that without using, for exemple, /blog/categories/view/:alias ?
Note: I have the same problem for /blog/ (list all articles) and /blog/:alias/ (display single article).
By including 'alias' => null you're specifying a default value for the :alias parameter, used if it is not in the URL. This is why your second route is always matching. Remove this and it should work as you are wanting it to.
I've got 2 links in my layout.phtml and a route in the bootstrap:
1. Link:
echo $this->url(array('controller' => 'aktuelles', 'action' => 'index'), null, true );
// creates: http://localhost/aktuelles
2: Link
echo $this->url(array('controller' => 'projekte', 'action' => 'wohnen', 'projektId' => 26), 'projekte-galeria', false);
// creates: http://localhost/projekte/wohnen/26
Route:
$front = Zend_Controller_Front::getInstance();
$router = $front->getRouter();
$route = new Zend_Controller_Router_Route( 'projekte/wohnen/:projektId',
array(
'module' => 'web',
'controller' => 'projekte',
'action' => 'wohnen',
'projektId' => null)
);
$router->addRoute( 'projekte-galeria', $route);
When I load the page everything is displayed correctly and the urls are all correct.
Problem: As soon as i click on the second link (http://localhost/projekte/wohnen/26), the first link is changing:
from: localhost/aktuelles
to : localhost/projekte/wohnen
Why is the link changed?
Try to force to use the default route: instead of null use 'default' as the second parameter in the first url.
BTW - the part 'controller' => 'projekte', 'action' => 'wohnen' in the second url is redundant, because you predefine these parameters in the route. The second link could by simplified like this:
echo $this->url(array('projektId' => 26), 'projekte-galeria', false);
Have a look at this solution as an alternative way to handle routes Simple rewrites in Zend Framework
Is it possible in CakePHP to have URL aliases in routes.php? Or by what other means can achieve something equivalent:
Lets assume I have some paginated views. Among the possible orderings there are particular ones I want to bind to a simple URL. E.g.:
http://example.com/headlines => http://example.com/posts/listView/page:1/sort:Post.created/direction:desc
http://example.com/hottopics => http://example.com/posts/listView/page:1/sort:Post.view_count/direction:desc etc.
How do I add parameters to a Router::connect()? Pseudo code:
Router::connect('/'.__('headlines',true),
array(
'controller' => 'posts',
'action' => 'listView'
'params' => 'page:1/sort:Post.created/direction:desc',
)
);
Note that the Router "translates" a URL into Controllers, Actions and Params, it doesn't "forward" URLs to other URLs. As such, write it like this:
Router::connect('/headlines',
array(
'controller' => 'posts',
'action' => 'listView'
'page' => 1,
'sort' => 'Post.created',
'direction' => 'desc'
)
);
I don't think '/'.__('headlines', true) would work, since the app is not sufficiently set up at this point to translate anything, so you'd only always get the word in your default language back. Also, you couldn't switch the language anymore after this point, the first use of __() locks the language.
You would need to connect all URLs explictly. To save you some typing, you could do this:
$headlines = array('en' => 'headlines', 'de' => 'schlagzeilen', ...);
foreach ($headlines as $lang => $headline) {
Router::connect("/$headline", array('controller' => ..., 'lang' => $lang));
}
That will create a $this->param['named']['lang'] variable, which you should use in the URL anyway.
Yes, it is possible... Bootstrap.php loads before routes so if you set there something like:
session_start();
if(isset($_SESSION['lng'])){
Configure::write('Config.language', $_SESSION['lng']);
}
...and in your app controller in beforeFilter:
$language = 'xy';
Configure::write('Config.language', $language);
$_SESSION['lng'] = $language;
So initial page render you prompt for language, redirect to xy.site.com or www.site.com/xy whatever you prefer. Now second render will change $language and on page links and set $_SESSION['lang']...
All router links like:
Router::connect(__('/:gender/search/:looking_for/*'), array('controller' => 'users', 'action' => 'search'));
will become:
Router::connect(__('/:gender/trazi/:looking_for/*'), array('controller' => 'users', 'action' => 'search'));
or:
Router::connect(__('/:gender/suche/:looking_for/*'), array('controller' => 'users', 'action' => 'search'));
100% tested, works in CakePHP 2.2. Also further improvement is possible if you put subdomain/language url parser in the bootstrap itself...