I've updated Akrabat_Router to take advantage of a patch posted by Christopher Thompson on the fw-general list. I've also put in support for using traditional request variables so that I can have urls like http://localhost/zf_test/index.php?command=user&action=login etc. This is mainly for use with IIS as ISAPI_Rewrite costs money :)
The class now looks like this:
<?php /** * This is a direct copy of Zend_Controller_Router altered * to allow for the controller to be in a sub-directory of * the web root. * * Includes a patch from Christopher Thompson */ /** Zend_Controller_Router_Interface */ require_once 'Zend/Controller/Router/Interface.php'; /** Zend_Controller_Dispatcher_Interface */ require_once 'Zend/Controller/Dispatcher/Interface.php'; /** Zend_Controller_Router_Exception */ require_once 'Zend/Controller/Router/Exception.php'; /** Zend_Controller_Dispatcher_Token */ require_once 'Zend/Controller/Dispatcher/Token.php'; class Akrabat_Controller_Router implements Zend_Controller_Router_Interface { private $script_extension; public function __construct($script_extension='.php') { $this->script_extension = $script_extension; } public function route(Zend_Controller_Dispatcher_Interface $dispatcher) { /** * @todo Replace with Zend_Request object */ $path = $_SERVER['REQUEST_URI']; if (stripos($path, $this->script_extension) !== FALSE) { $base = $_SERVER['SCRIPT_NAME']; // using script name } else { $base = dirname($_SERVER['SCRIPT_NAME']); // using rewrite rules } $path = substr($path, strlen($base)); if (strstr($path, '?')) { $path = substr($path, 0, strpos($path, '?')); } if(strlen($path) == 0) { // look for command line parameters where POST overides GET $filterGet = zend::registry('filterGet'); /* @var $filterGet Akrabat_InputFilter */ $filterPost = zend::registry('filterPost'); /* @var $filterPost Zend_InputFilter */ $command = $filterPost->getAlphaWithDefault('command', $filterGet->getAlphaWithDefault('command')); $action = $filterPost->getAlphaWithDefault('action', $filterGet->getAlphaWithDefault('action')); $path[0] = $command; $path[1] = $action; } else { $path = explode('/', trim($path, '/')); } /** * The controller is always the first piece of the URI, and * the action is always the second: * * http://zend.com/controller-name/action-name/ */ $controller = $path[0]; $action = isset($path[1]) ? $path[1] : null; /** * If no controller has been set, IndexController::index() * will be used. */ if (!strlen($controller)) { $controller = 'index'; $action = 'index'; } /** * Any optional parameters after the action are stored in * an array of key/value pairs: * * http://www.zend.com/controller-name/action-name/param-1/3/param-2/7 * * $params = array(2) { * ["param-1"]=> string(1) "3" * ["param-2"]=> string(1) "7" * } */ $params = array(); for ($i=2; $i<sizeof ($path); $i=$i+2) { $params[$path[$i]] = isset($path[$i+1]) ? $path[$i+1] : null; } $token = new Zend_Controller_Dispatcher_Token($controller, $action, $params); if (!$dispatcher->isDispatchable($token)) { /** * @todo error handling for 404's */ throw new Zend_Controller_Router_Exception('Request could not be mapped to a route.'); } else { return $token; } } } ?>
The interesting stuff is at the top of route(). Note that the code assumes that your index.php has this code:
$filterPost = new Akrabat_InputFilter($_POST); $filterGet = new Akrabat_InputFilter($_GET); Zend::register('filterPost', $filterPost); Zend::register('filterGet', $filterGet);
Also, I had to derive Akrabat_InputFilter from Zend_InputFilter to provide getXxxxWithDefault() functionality.
Akrabat_InputFilter looks like this:
<?php /** Zend_Controller_Router_Interface */ require_once 'Zend/InputFilter.php'; class Akrabat_InputFilter extends Zend_InputFilter { public function exists($key) { return isset($this->_source[$key]); } /** * Returns only the alphabetic characters in value. * * @param mixed $key * @return mixed */ public function getAlphaWithDefault($key, $default='') { if($this->exists($key)) { return Zend_Filter::getAlpha($this->_source[$key]); } else { return $default; } } /** * Returns only the digits in value. This differs from getInt(). * * @param mixed $key * @return mixed */ public function getDigitsWithDefault($key, $default=0) { if($this->exists($key)) { return Zend_Filter::getDigits($this->_source[$key]); } else { return (int)$default; } } // more getXxxxWithDefault() as required }
I'm getting quite a collection of Akrabat_ overrides for Zend_ classes now. I fully expect that most of them will be redundant by 1.0!


