Search code examples
phpyiiyii-componentsmagic-methods

Yii's magic method for controlling all actions under a controller


Commando need's help from you.

I have a controller in Yii:

class PageController extends Controller {
    public function actionSOMETHING_MAGIC($pagename) {
        // Commando will to rendering,etc from here
    }
}

I need some magic method under Yii CController for controlling all subrequest under /page || Page controller.

Is this somehow possible with Yii?

Thanks!


Solution

  • Sure there is. The easiest way is to override the missingAction method.

    Here is the default implementation:

    public function missingAction($actionID)
    {
        throw new CHttpException(404,Yii::t('yii','The system is unable to find the requested action "{action}".',
            array('{action}'=>$actionID==''?$this->defaultAction:$actionID)));
    }
    

    You could simply replace it with e.g.

    public function missingAction($actionID)
    {
        echo 'You are trying to execute action: '.$actionID;
    }
    

    In the above, $actionID is what you refer to as $pageName.

    A slightly more involved but also more powerful approach would be to override the createAction method instead. Here's the default implementation:

    /**
     * Creates the action instance based on the action name.
     * The action can be either an inline action or an object.
     * The latter is created by looking up the action map specified in {@link actions}.
     * @param string $actionID ID of the action. If empty, the {@link defaultAction default action} will be used.
     * @return CAction the action instance, null if the action does not exist.
     * @see actions
     */
    public function createAction($actionID)
    {
        if($actionID==='')
            $actionID=$this->defaultAction;
        if(method_exists($this,'action'.$actionID) && strcasecmp($actionID,'s')) // we have actions method
            return new CInlineAction($this,$actionID);
        else
        {
            $action=$this->createActionFromMap($this->actions(),$actionID,$actionID);
            if($action!==null && !method_exists($action,'run'))
                    throw new CException(Yii::t('yii', 'Action class {class} must implement the "run" method.', array('{class}'=>get_class($action))));
            return $action;
        }
    }
    

    Here for example, you could do something as heavy-handed as

    public function createAction($actionID)
    {
        return new CInlineAction($this, 'commonHandler');
    }
    
    public function commonHandler()
    {
        // This, and only this, will now be called for  *all* pages
    }
    

    Or you could do something way more elaborate, according to your requirements.