Zend Framework URLs without mod_rewrite
Some of our Zend Framework applications have to run on IIS without ISAPI_Rewrite installed. In these cases we need urls of the form http://www.example.com/index.php?module=mod&controller=con&action=act. I couldn't get this to work out of the box with Zend Framework 1.5, so wrote my own router called App_Controller_Router_Route_RequestVars.
This code obviously only supports what I needed and I've only tested it on IIS for Windows 2003 Server, so you may need to tweak to make it do what you want! Feel free to share any fixes :)
This is the code:
<?php /** Zend_Controller_Router_Exception */ require_once 'Zend/Controller/Router/Exception.php'; /** Zend_Controller_Router_Route_Interface */ require_once 'Zend/Controller/Router/Route/Interface.php'; /** * Route * * @package App_Controller * @subpackage Router * @copyright Copyright (c) 2008 Rob Allen (rob@akrabat.com) */ class App_Controller_Router_Route_RequestVars implements Zend_Controller_Router_Route_Interface { protected $_current = array(); /** * Instantiates route based on passed Zend_Config structure */ public static function getInstance(Zend_Config $config) { return new self(); } /** * Matches a user submitted path with a previously defined route. * Assigns and returns an array of defaults on a successful match. * * @param string Path used to match against this routing map * @return array|false An array of assigned values or a false on a mismatch */ public function match($path) { $frontController = Zend_Controller_Front::getInstance(); $request = $frontController->getRequest(); /* @var $request Zend_Controller_Request_Http */ $baseUrl = $request->getBaseUrl(); if (strpos($baseUrl, 'index.php') !== false) { $url = str_replace('index.php', '', $baseUrl); $request->setBaseUrl($url); } $params = $request->getParams(); if (array_key_exists('module', $params) || array_key_exists('controller', $params) || array_key_exists('action', $params)) { $module = $request->getParam('module', $frontController->getDefaultModule()); $controller = $request->getParam('controller', $frontController->getDefaultControllerName()); $action = $request->getParam('action', $frontController->getDefaultAction()); $result = array('module' => $module, 'controller' => $controller, 'action' => $action, ); $this->_current = $result; return $result; } return false; } /** * Assembles a URL path defined by this route * * @param array An array of variable and value pairs used as parameters * @return string Route path with user submitted parameters */ public function assemble($data = array(), $reset=false) { $frontController = Zend_Controller_Front::getInstance(); if(!array_key_exists('module', $data) && !$reset && array_key_exists('module', $this->_current) && $this->_current['module'] != $frontController->getDefaultModule()) { $data = array_merge(array('module'=>$this->_current['module']), $data); } if(!array_key_exists('controller', $data) && !$reset && array_key_exists('controller', $this->_current) && $this->_current['controller'] != $frontController->getDefaultControllerName()) { $data = array_merge(array('controller'=>$this->_current['controller']), $data); } if(!array_key_exists('action', $data) && !$reset && array_key_exists('action', $this->_current) && $this->_current['action'] != $frontController->getDefaultAction()) { $data = array_merge(array('action'=>$this->_current['action']), $data); } $url = ''; if(!empty($data)) { $urlParts = array(); foreach($data as $key=>$value) { $urlParts[] = $key . '=' . $value; } $url = '?' . implode('&', $urlParts); } return $url; } }
This route is then added to the Front Controller's router in my bootstrap like this:
$frontController = Zend_Controller_Front::getInstance(); $router = $frontController->getRouter(); $router->addRoute('requestVars', new App_Controller_Router_Route_RequestVars());
Hopefully this is a useful starting point for others who can't use mod_rewrite with Zend Framework.

June 3rd, 2008 at 14:37 #
Great!
I needed something similar, but by luck my client agreed to use the Apache with mod_rewrite.
I will look your classe later and i will do some tests using IIS with windows vista.
Best regards,
June 4th, 2008 at 19:05 #
What about Apache's ErrorHandler directive? Much more elegant/simple/fast :)
June 4th, 2008 at 19:06 #
Forgot the second paragraph somehow, sorry.
Doesn't IIS provide something similar?
June 8th, 2008 at 08:15 #
I had the problem of no mod_rewrite support for a University problem. Although solved it by setting the baseUrl to /index.php, so the URLs were: /index.php/module/controller/action
This seemed to do the trick also.
I was originally trying to do request vars though. Nice work.
June 28th, 2008 at 14:44 #
What about
1. getting browser requests with $_SERVER['REQUEST_URI']
2. and using it like: index.php?/controller/action
August 13th, 2008 at 16:06 #
I believe there is a much easier way to do this, although I've not worked with the module concept but think it would work fine. If you (the owner of the site) want to contact me, then I'd be interested to see what you think.
A
January 21st, 2009 at 08:50 #
I am getting the following error
Class 'Application_Controllers_Router_Route_RequestVars' not found in D:\xampp\htdocs\sample\public\index.php on line 34
Please advise what may be the reasons.
I have checked the path also.
January 21st, 2009 at 08:52 #
AKS,
Have you enabled the autoloader in your index.php file?
Regards,
Rob...
January 21st, 2009 at 09:54 #
Thanks a Heap Rob !!!
Now it is working perfectly
Thanks for the help
Regards,
AKS
April 27th, 2009 at 08:09 #
hehehe
thank's Rob
this is what i need, i hope this work int my (work) environment.
June 16th, 2009 at 13:10 #
Thanks Rob for fantastic article.
This works for both webserver apache as well IIS. I have one query regarding above example. This router will work for all custom URLs. but if I have some URLs which have original controllers. How can I handle that with custom router.
Means:
http://www.abc.com/xyz-opq
is working fine but if I have below URL
http://www.abc.com/news
News controller is already available on the application so how could I handle and forward to same controller. Is there any option to check whether controller is exist or not in match method?
Highly appreciate your response.
Best Regards,
December 11th, 2009 at 17:28 #
Pls help,
I don't know how to enable the autoloader in my index.php file!
Thanks!