Changing Theme On-The-Fly

I’m developing an app and for some specific controllers I need to change the Theme,

i.e: Theme for user and theme for admin.

At config/main.php:


'theme'=>'userTheme',

I tried using this code right before the Class that extends the Controller and it works flawlessly!


Yii::app()->theme = 'adminTheme';

class AdminController extends Controller

{

......

}

When I got back to the other controllers the theme changed back to the theme I set-up at main.php, as I expected.

I want know if it’s a good solution to change themes on-the-fly or it is something very unusual and a lot out of standards?

Hi,

I’ve made a themeable app which allows users to choose the theme they want, as well as using a predefined theme or their favorite theme when logged in. Haven’t published it here, but the solution I found was to create a BaseController and inside the init function I put the code

components/BaseController.php




public function init(){

    Yii::app()->theme = Yii::app()->user->getCurrentTheme();

    

    parent::init()

}



in WebUser.php component:




                //session theme not defined

		if(empty(Yii::app()->session['currentTheme'])):

			

			//user is guest, load default theme

			if (Yii::app()->user->isGuest):

                                //here you can do your trick to load a default theme, I won't go beyond into Theme::getDefaultTheme() because that is unnecessary to the case you mentioned,you could just put 'default' here

				Yii::app()->session['currentTheme'] = Theme::getDefaultTheme();  // = 'classic or default'

			else:

				$user = $this->loadUser(Yii::app()->user->getId());

				if ($user->theme_name && $user->theme->status == Theme::STATUS_ONLINE): //or if($user->isAdmin()) 

					Yii::app()->session['currentTheme'] = $user->theme_name;

				else:

					Yii::app()->session['currentTheme'] = Theme::getDefaultTheme();

				endif;

			endif;

		endif;

		

		return Yii::app()->session['currentTheme'];



All you have to do now is to extend your controllers from this BaseController.php, once it is under components and usually all components are automatically loaded, so do like




class SiteController extends BaseController{


    //no need to worry about init(), because it is inherited




    public function actionIndex(){}


    public function actionLogin(){}


...

}



Hope this helps

Regards

ps.

In my opinion, it is smart and gives the website a "plus" the ability to change themes on-the-fly

:)

Thanks for this example. Into which method / function did you put this code?

When you create a module eg frontend, a file name FrontendModule.php is created automatically by gii.

The file will have an action called beforeControllerAction where you can do all sorts of tests. This function is called before any controller or its actions are called in a module. So you can do module wide tests and changes here.




public function beforeControllerAction($controller, $action)

	{

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

		{

			// this method is called before any module controller action is performed

			// you may place customized code here


                    //change theme for the entire module

                    Yii::app()->theme = 'myThemeName';


                   //or for specific actions 

                   if($action->id == 'services'){

                       Yii::app()->theme = 'myThemeName';

                 }


                 //or for specific controller

                   if($controller->id == 'payment'){

                       Yii::app()->theme = 'myThemeName';

                 }


                //or test for both

                  if($controller->id == 'payment'  && $action->id == 'services'){

                       Yii::app()->theme = 'myThemeName';

                 }


			return true;

		}

		else

			return false;

	}



Old thread, but I found another method: make your own ThemeManager:

<?php

class YThemeManager extends CThemeManager {

public function getTheme(&#036;theme) {


    &#036;user=AppUtils::getCurrentUser();


    if(&#036;user&#33;==null) {


        &#036;usertheme=&quot;{&#036;user-&gt;theme}&quot;;


        if(&#036;usertheme&#33;=='') {


            &#036;theme=&#036;usertheme;


        }


    }


    return parent::getTheme(&#036;theme);


}

}

In the above, I call a utility method of mine to get the current user model (AppUtils::getCurrentUser).

The method then tests if there is a theme for the user, if yes, it uses it to call the default thememanager method.

To use this class, you have to set it in your configuration:

‘components’=>array(‘themeManager’=>array(‘class’=>‘YThemeManager’), …)