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 Responses to “Zend Framework URLs without mod_rewrite”

  1. 1 Adler Medrado

    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. 2 Lars

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

  3. 3 Lars

    Forgot the second paragraph somehow, sorry.

    Doesn't IIS provide something similar?

  4. 4 Tom Graham

    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. 5 Beysim

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

  6. 6 Antony

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

    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.

  8. 8 Rob...

    AKS,

    Have you enabled the autoloader in your index.php file?

    Regards,

    Rob...

  9. 9 AKS

    Thanks a Heap Rob !!!

    Now it is working perfectly

    Thanks for the help

    Regards,
    AKS

  10. 10 quantro

    hehehe

    thank's Rob
    this is what i need, i hope this work int my (work) environment.

  11. 11 Amit Shah

    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,

  12. 12 Dang

    Pls help,
    I don't know how to enable the autoloader in my index.php file!
    Thanks!

  13. 13 Oro

    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 library\Zend\Controller\Router\Route ?
    -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

  14. 14 Rob...

    Oro,

    App_Controller_Router_Route_RequestVars would live in library\App\Controller\Router\Route\RequestVars.php

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

    Regards,

    Rob...

  15. 15 Oro

    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

  16. 16 Oro

    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 \library\Zend\Application\Bootstrap\Bootstrap.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

  17. 17 Rob...

    Oro,

    You'll have to update the code to work with ZF 1.10.

    Regards,

    Rob...

  18. 18 Oro

    Hello

    Rob, our ZF project is written to work with ZF version 1.10.5

    Regards

    Oro

  19. 19 klose

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

  20. 20 swati

    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 ?

  21. 21 Rob...

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

  22. 22 swati

    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 ?

  23. 23 Julio Cesar

    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

  24. 24 Jordi

    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?

  25. 25 Rob...

    JC,

    http://akrabat.com/licensing

    Regards,

    Rob...

The views expressed in these comments are not the views of the publisher. However, we believe in the rights of others to express their legitimate views and concerns. Any legitimate complaint emailed to rob@akrabat.com will be seriously considered and the post reviewed as desirable and necessary.