I have extended Zend_Controller_Action with my controller class and made the following changes:
In dispatch($action) method replaced
$this->$action();
with
call_user_func_array(array($this,$action), $this->getUrlParametersByPosition());
And added the following method
/**
* Returns array of url parts after controller and action
*/
protected function getUrlParametersByPosition()
{
$request = $this->getRequest();
$path = $request->getPathInfo();
$path = explode('/', trim($path, '/'));
if(@$path[0]== $request->getControllerName())
{
unset($path[0]);
}
if(@$path[1] == $request->getActionName())
{
unset($path[1]);
}
return $path;
}
Now for a URL like /mycontroller/myaction/123/321
in my action I will get all the params following controller and action
public function editAction($param1 = null, $param2 = null)
{
// $param1 = 123
// $param2 = 321
}
Extra parameters in URL won't cause any error as you can send more params to method then defined. You can get all of them by func_get_args()
And you can still use getParam() in a usual way.
Your URL may not contain action name using default one.
Actually my URL does not contain parameter names. Only their values. (Exactly as it was in the question)
And you have to define routes to specify parameters positions in URL to follow the concepts of framework and to be able to build URLs using Zend methods.
But if you always know the position of your parameter in URL you can easily get it like this.
That is not as sophisticated as using reflection methods but I guess provides less overhead.
Dispatch method now looks like this:
/**
* Dispatch the requested action
*
* @param string $action Method name of action
* @return void
*/
public function dispatch($action)
{
// Notify helpers of action preDispatch state
$this->_helper->notifyPreDispatch();
$this->preDispatch();
if ($this->getRequest()->isDispatched()) {
if (null === $this->_classMethods) {
$this->_classMethods = get_class_methods($this);
}
// preDispatch() didn't change the action, so we can continue
if ($this->getInvokeArg('useCaseSensitiveActions') || in_array($action, $this->_classMethods)) {
if ($this->getInvokeArg('useCaseSensitiveActions')) {
trigger_error('Using case sensitive actions without word separators is deprecated; please do not rely on this "feature"');
}
//$this->$action();
call_user_func_array(array($this,$action), $this->getUrlParametersByPosition());
} else {
$this->__call($action, array());
}
$this->postDispatch();
}
// whats actually important here is that this action controller is
// shutting down, regardless of dispatching; notify the helpers of this
// state
$this->_helper->notifyPostDispatch();
}