Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

zend: parameter collision

I wonder why no one ever asked this question.

Every zend Action function in controller class has 3 paramters, namely 'module', 'controller', and 'action'.

What happens, when I get a parameter named 'action' from a form or url, for example "?action=edit" ??

I tested it: action holds its value from router, not 'edit'.

public function someAction() {
    $params = $this->getRequest()->getParams();
...

How could I pass the parameter named "action", if I had to ??

Thanks in advance.

like image 472
user1592714 Avatar asked Oct 23 '22 11:10

user1592714


2 Answers

The default route is Zend_Controller_Router_Route_Module which uses default keys for module, controller, & action:

protected $_moduleKey     = 'module';
protected $_controllerKey = 'controller';
protected $_actionKey     = 'action';

// ...

/**
 * Set request keys based on values in request object
 *
 * @return void
 */
protected function _setRequestKeys()
{
    if (null !== $this->_request) {
        $this->_moduleKey     = $this->_request->getModuleKey();
        $this->_controllerKey = $this->_request->getControllerKey();
        $this->_actionKey     = $this->_request->getActionKey();
    }

    if (null !== $this->_dispatcher) {
        $this->_defaults += array(
            $this->_controllerKey => $this->_dispatcher->getDefaultControllerName(),
            $this->_actionKey     => $this->_dispatcher->getDefaultAction(),
            $this->_moduleKey     => $this->_dispatcher->getDefaultModule()
        );
    }

    $this->_keysSet = true;
}

/**
 * Matches a user submitted path. Assigns and returns an array of variables
 * on a successful match.
 *
 * If a request object is registered, it uses its setModuleName(),
 * setControllerName(), and setActionName() accessors to set those values.
 * Always returns the values as an array.
 *
 * @param string $path Path used to match against this routing map
 * @return array An array of assigned values or a false on a mismatch
 */
public function match($path, $partial = false)
{
    $this->_setRequestKeys();

    $values = array();
    $params = array();

    if (!$partial) {
        $path = trim($path, self::URI_DELIMITER);
    } else {
        $matchedPath = $path;
    }

    if ($path != '') {
        $path = explode(self::URI_DELIMITER, $path);

        if ($this->_dispatcher && $this->_dispatcher->isValidModule($path[0])) {
            $values[$this->_moduleKey] = array_shift($path);
            $this->_moduleValid = true;
        }

        if (count($path) && !empty($path[0])) {
            $values[$this->_controllerKey] = array_shift($path);
        }

        if (count($path) && !empty($path[0])) {
            $values[$this->_actionKey] = array_shift($path);
        }

        if ($numSegs = count($path)) {
            for ($i = 0; $i < $numSegs; $i = $i + 2) {
                $key = urldecode($path[$i]);
                $val = isset($path[$i + 1]) ? urldecode($path[$i + 1]) : null;
                $params[$key] = (isset($params[$key]) ? (array_merge((array) $params[$key], array($val))): $val);
            }
        }
    }

    if ($partial) {
        $this->setMatchedPath($matchedPath);
    }

    $this->_values = $values + $params;

    return $this->_values + $this->_defaults;
}

You can see that the default module route has default keys for mvc params, however, it will use the keys set by the request object if it exists and we can modify these keys.

e.g. in your bootstrap:

class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
    protected function _initRequestKeys()
    {
        $this->bootstrap('frontcontroller');
        $frontController = $this->getResource('frontcontroller');
        /* @var $frontController Zend_Controller_Front */

        $request = new Zend_Controller_Request_Http();

        // change action key
        $request->setActionKey("new_action_key");

        // change module
        $request->setModuleKey("new_module_key");

        // change controller
        $request->setControllerKey("new_controller_key");


        // don't forget to set the configured request
        // object to the front controller
        $frontController->setRequest($request);
    }
}

Now you can use module, controller, & action as $_GET params.

like image 121
Gerard Roche Avatar answered Dec 22 '22 00:12

Gerard Roche


After a little testing it seems that how you pass the key "action" matters.

If you try and pass a parameter named "action" with $this->_request->getParams() you will get the controller action value key pair.

If you pass the "action" key from a form with $form->getValues() you will retrieve the value from the form element named "action".

As with so many things, your use case determines how you need to handle the situation.

Good Luck.

like image 34
RockyFord Avatar answered Dec 22 '22 01:12

RockyFord