Add a new controller event, onBeforeControllerInit

Is there any chance to change CWebApplication::runController so that before $controller->init(); is called to have an event where we can attach event handlers from other components ?

Maybe something like:




public function onBeforeControllerInit($event)

{

    $this->raiseEvent('onBeforeControllerInit', $event);

}


public function runController($route)

{

	if(($ca=$this->createController($route))!==null)

	{

		list($controller,$actionID)=$ca;

		$oldController=$this->_controller;

		$this->_controller=$controller;

		if($this->hasEventHandler('onBeforeControllerInit'))

                    $this->onBeforeControllerInit(new CEvent($controller));

                $controller->init();

		$controller->run($actionID);

		$this->_controller=$oldController;

	}

	else

		throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',

			array('{route}'=>$route===''?$this->defaultController:$route)));

}



Then from our components we could:




//component init() method maybe

Yii::app()->attachEventHandler('onBeforeControllerInit', array($this, 'runOnBeforeControllerInit'));




public function runOnBeforeControllerInit($event){

   $c=$event->sender;

   if(!($c instanceof SiteController))

      return;

   // do things like attach new behaviors, etc for the SiteController controller.

}



I’m asking this because most of the time i see myself searching for a way to hook from my components into controllers before they run, so that i can attach behaviors to them.

Why can’t you do it in the controller init()?

Because i need to be able to hook into the controller from the application instance, not by getting an instance of the controller then hook into it.

If i needed to hook from within controller, i would do smth like:




class MyController extends Controller{


   public function init()

   {

       if($this->hasEventHandler('onBeforeControllerInit')){

            $this->onBeforeControllerInit(new CEvent($this));

       }

       parent::init();

   }


   public function onBeforeControllerInit($event)

   {

       $this->raiseEvent('onBeforeControllerInit', $event);

   }


}



And hook in it from components like:




Yii::app()->getController()->attachEventHandler('onBeforeControllerInit', array($this,'someHandler'));



But this poses allot of problems, first of all, the controller needs to be instantiated to hook into it, and at the point it is instantiated, the init() method has already been called, therefore the event won’t be raised anymore.

Beside this issue, what if i need to attach handlers before the controller is instantiated, say from preloaded components ?

Remember, this is needed to hook into controllers from within components, even if the controller hasn’t been instantiated yet, giving a flexible way to alter controllers without needing to change the controller code itself.

Wouldn’t CApplication’s onBeginRequest do the trick? I think, it’s triggered after the preload components where loaded.

@Mike

In onBeginRequest you don’t have access to the controller instance (Yii::app()->getController() is null) so this is useless.

We need to have a way to hook into controllers (set the event handler before the controller instantiates, and raise the event when the controller gets instantiated)

posted on github because here no dev team member is looking as far as i can see.