Pragmatism in the real world

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.

25 thoughts on “Zend Framework URLs without mod_rewrite

  1. 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,

  2. What about Apache's ErrorHandler directive? Much more elegant/simple/fast :)

  3. Forgot the second paragraph somehow, sorry.

    Doesn't IIS provide something similar?

  4. 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.

  5. What about
    1. getting browser requests with $_SERVER['REQUEST_URI']
    2. and using it like: index.php?/controller/action

  6. 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

  7. I am getting the following error
    Class 'Application_Controllers_Router_Route_RequestVars' not found in D:xampphtdocssamplepublicindex.php on line 34

    Please advise what may be the reasons.

    I have checked the path also.

  8. 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,

  9. Hello Rob could you give us the required step to configure Zend Framework without use mod_rewrite (with IIS) ?
    -Where is it possible to use App_Controller_Router_Route_RequestVars ?
    Shall we create a file called RequestVars.php inside libraryZendControllerRouterRoute ?
    -Where ( the php file) we must add the lines

    $frontController = Zend_Controller_Front::getInstance();
    $router = $frontController->getRouter();
    $router->addRoute('requestVars', new App_Controller_Router_Route_RequestVars())

    Thanks

    Oro

  10. Oro,

    App_Controller_Router_Route_RequestVars would live in libraryAppControllerRouterRouteRequestVars.php

    The rest would go in your Bootstrap class in ZF 1.10.x.

    Regards,

    Rob…

  11. Thanks for your answer,Rob
    Can you give more details about where I must to put

    $frontController = Zend_Controller_Front::getInstance();
    $router = $frontController->getRouter();
    $router->addRoute('requestVars', new App_Controller_Router_Route_RequestVars())

    beacause I've tried with this error

    Class 'Application_Controllers_Router_Route_RequestVars' not found

    Thanks

    Oro

  12. Hello Rob, just an other update.I have tried to add the lines

    $frontController = Zend_Controller_Front::getInstance();
    $router = $frontController->getRouter();
    $router->addRoute('requestVars', new App_Controller_Router_Route_RequestVars())

    in the file libraryZendApplicationBootstrapBootstrap.php but I have this error

    "Fatal error: Declaration of App_Controller_Router_Route_RequestVars::assemble() must be compatible with that of Zend_Controller_Router_Route_Interface::assemble() in ..RequestVars.php"

    Thanks

    Oro

  13. please where in zf do i include the router class. im having problem accessign my application on windows becuase of the ISAP REWRITE

  14. Hello sir,
    i have to use zend with iis and i m using ISAPI_Rewrite installed , but wn i run any controller/action it gives page not found error , can you help to fix this bug ?

    i have installed the things as follows :
    c:/ – php
    c:/program files – Mysql
    c:/Inetpub/wwwroot/ – zend framework
    c:/Inetpub/wwwroot/ – isapi_rewrite
    c:/Inetpub/wwwroot/ – tzend (a project in zend )

    when i run http://localhost/tzend/public
    welcome page gets displayed , but
    when i run
    http://localhost/tzend/public/index/add
    Page Not found errror comes
    can you help me any how to fix this bug ?

    1. I've not used ISAPI_Rewrite, but I would guess that the ISAPI_Rewrite module is either not enabled or not configured correctly to do redirections from the directory.

      Regards,

      Rob…

  15. sir i isapi_rewrite is installed properly since the .htaccess file shows helicon- isapi_rewrite and when try to open it it gets open in helicon – isapi_rewrite editor ..

    i think some changes to be done to the content of .htaccess file since it is set to work in apache and now i want it towrk in windows so, some changes would be there ..

    please let me now , if you can help in any way ?

  16. Hi, Rob, I would like how I implement the Rewrite without ISAPI in IIS using only Boostrap and Zend_Controller_Router_Rewrite for solv my problem

    Thankz

    JC

  17. Hi, i see that you've assigned the code license as copyright. Under which license can we use it? GPL is a possibility, so we can use freely?

Comments are closed.