How does the method syntax “public function direct

2019-05-21 05:03发布

问题:

I'm learning Zend Framework at the moment and came across the following syntax.

class Zend_Controller_Action_Helper_Redirector extends Zend_Controller_Action_Helper_Abstract
{
    /**
     * Perform a redirect to an action/controller/module with params
     *
     * @param  string $action
     * @param  string $controller
     * @param  string $module
     * @param  array  $params
     * @return void
     */
    public function gotoSimple($action, $controller = null, $module = null, array $params = array())
    {
        $this->setGotoSimple($action, $controller, $module, $params);

        if ($this->getExit()) {
            $this->redirectAndExit();
        }
    }

    /**
     * direct(): Perform helper when called as
     * $this->_helper->redirector($action, $controller, $module, $params)
     *
     * @param  string $action
     * @param  string $controller
     * @param  string $module
     * @param  array  $params
     * @return void
     */
    public function direct($action, $controller = null, $module = null, array $params = array())
    {
        $this->gotoSimple($action, $controller, $module, $params);
    }
}

In Zend Framework the direct() method in this class can be called using the following syntax:

$this->_helper->redirector('index','index');

Where redirector is an object(!) in the _helper object, which is inside the controller object, in which we call the method. The syntactic sugar here is that you can just pass parameters to the object instead of to the method, which we would write like so:

$this->_helper->redirector->gotoSimple('index','index');

..which is all fine and dandy ofcourse.

Here's my question: is this direct() method standard in OO PHP? Or is this functionality built into Zend Framework? I can't find any documentation on this.

Thanks!

回答1:

It is functionality build into Zend Framework.

The $_helpers property in the Controller instance holds an Action_HelperBroker instance. This instance implements PHP's magic __call method. When you call a method that does not exist on that instance, it will try to use the method name to fetch a helper of the same name and call direct() on it (if possible). See code below.

From Zend_Controller_Action

/**
 * Helper Broker to assist in routing help requests to the proper object
 *
 * @var Zend_Controller_Action_HelperBroker
 */
protected $_helper = null;

From Zend_Controller_Action_HelperBroker

/**
 * Method overloading
 *
 * @param  string $method
 * @param  array $args
 * @return mixed
 * @throws Zend_Controller_Action_Exception if helper does not have a direct() method
 */
public function __call($method, $args)
{
    $helper = $this->getHelper($method);
    if (!method_exists($helper, 'direct')) {
        require_once 'Zend/Controller/Action/Exception.php';
        throw new Zend_Controller_Action_Exception('Helper "' . $method . '" does not support overloading via direct()');
    }
    return call_user_func_array(array($helper, 'direct'), $args);
}

The Helper Broker also implement the magic __get method, so when you try to access a property that does not exist, the broker will use the property name as an argument to getHelper()

/**
 * Retrieve helper by name as object property
 *
 * @param  string $name
 * @return Zend_Controller_Action_Helper_Abstract
 */
public function __get($name)
{
    return $this->getHelper($name);
}

Please be aware that magic methods are not meant as a replacement to a proper API. While you can use them as shown above, calling the more verbose

$this->_helper->getHelper('redirector')->gotoSimple('index','index');

is often the much faster alternative.