How To Dynamically Specify Layout Name In A Module?

Hi,

I have a problem…

By using Yii-Boilerplate, I have directory structure like this:




/common

  /modules

    /user

      /controllers

      /views

/backend

  /controllers

  /views

  /www

/frontend

  /controllers

  /themes

  /www



As you can see I have a user module under common directory and it has some controllers which one of them is profileController:




class profileController extends Controller

{

  public function actionEdit()

  {

     //doing something


    $this->render('edit', $params);

  }

}



That controller should be able to be accessed from frontend and backend, and should follow the layout from where it is called (if it’s called from frontend, it should use frontend’s layout, so does for backend).

What I have done is creating a Controller in /frontend/components:




class Controller extends CController

{

  public $layout = '//layouts/frontend1';

}



So the profileController actually extends Controller class from frontend or backend (determined by separate config in frontend/backend) to inherit the layout name. I don’t specify it in the profileController since it’s in the module, where I think we shouldn’t hardcode the frontend/backend’s layout name there.

This approach does work, however if I have some layouts, I need to create many Controller classes just for specifying the layout name! So… is there any better solution for this?

Hi

I don’t know how the Yii boilerplate structure works but how about tried putting the following code in the beforeControllerAction function in your UserModule.php file?




public function beforeControllerAction($controller, $action)

	{

		if(parent::beforeControllerAction($controller, $action))

		{

			$controller->layout='//layouts/<layoutname>';

			// this method will be called before any controller action in that module takes place.

			return true;

		}

		else

			return false;

	}




Hi,

As per BlkRaven,

You can use beforeControllerAction function in your UserModule.php but your have to set a session or cookie or in GET method to specify from where the action comes from.

Say in your url add url?layout=admin or url?layout=frontend




public function beforeControllerAction($controller, $action)

        {

                if(parent::beforeControllerAction($controller, $action))

                {

                        if(Yii::app()->request->getQuery('layout') == 'admin')

                            $controller->layout='//layouts/<layoutname>'; //Admin layout name

                        else

                            $controller->layout='//layouts/<layoutname>'; //Front End layout name 

                        // this method will be called before any controller action in that module takes place.

                        return true;

                }

                else

                        return false;

        }



Even the above code not works just create a cookie and set the layout as follows




Yii::app()->request->cookies['layout'] = new CHttpCookie('layout', 'admin'); //When accessing from admin


Yii::app()->request->cookies['layout'] = new CHttpCookie('layout', 'frontend'); //When accessing from frontend



then change the beforeControllerAction accordingly…

If above all does’t works better go with session and use if condition with beforeControllerAction

Great, both of you enlightened me :) I didn’t know about beforeControllerAction before. I think I can use it combined with application parameter, which in YiiBoilerplate I can specify parameter in separated config for frontend and backend, so I’ll put the layout name there and read it in beforeControllerAction method.

Thanks guys!

check this wiki