Themes and css

I am theming my site and found it easy to follow the setup for alternate views etc. However, in the auto-generated code, the following code is used to render the css:


<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->request->baseUrl; ?>/css/screen.css" media="screen, projection" />

This doesn’t (afaik) take into account the current theme. I could use:


<link rel="stylesheet" type="text/css" href="<?php echo Yii::app()->theme->getBaseUrl(); ?>/css/screen.css" media="screen, projection" />

but this will break if there is no theme configured. Also, it doesn’t seem to follow the Yii approach. Is there a method somewhere that will check for a css in the current theme and if not found return the default, as with views?

If I can achieve the same thing a different way, then great.

Thanks

I’m new to Yii, so I’ve been scratching my head on this topic as well. To move forward, what I did here was create a dynamic baseUrl:




	<?php $baseUrl = (Yii::app()->theme ? Yii::app()->theme->baseUrl : Yii::app()->request->baseUrl); ?>

	<link rel="stylesheet" type="text/css" href="<?php echo $baseUrl; ?>/css/screen.css" media="screen, projection" />



This lets you leave the "unthemed" css folder where it is, and create a new css folder under each theme. I am undecided if this is better than keeping all css folders under themes, moving the "unthemed" css folder to themes/classic:




	<?php $baseUrl = (Yii::app()->theme ? Yii::app()->theme->baseUrl : Yii::app()->request->baseUrl . "/themes/classic"); ?>



I dislike both solutions because they put additional processing in the layout file.

No, that’s not the ‘right way to do it’ :)

Put the theme in ‘themes/yourtheme’.

Then put your views in themes/yourtheme/views.

That includes the main layout files, plus all theme dependent views.

That’s it. No parsing.

The only place you refer to your theme from outside of the themes directory would be when you set it, like in your config:


	'theme' => 'freshy2',



What Yii does, when you’ve set a theme is first look in your themes directory for a view.

If none is found, then it try and find one in protected/views.

I’m happy to follow the Yii Way as soon as I can grok it. :) Indoctrinate me, baby!

Putting the layout inside the theme folder makes sense to me, thanks. Is the right way to put all theme-specific files inside the themes folder, such as mytheme/css and mytheme/images?

Sorry about my lateness in indoctrinating… :)

But, it’s really neat when you know how:

1016

theme_1.png

What that was is the contents of my theme directory (protected/themes/my_theme).

You can see a views, css and images directory in there.

As you can see here, in the theme views directory, it’s a mirror of the ordinary protected/views directory:

1017

theme_2.png

This is the theme layouts:

1018

theme_3.png

If Yii doesn’t find a view in the current theme, it will look in protected/views, otherwise use what you put in your theme.

You can move all view files from protected/views if you are sure you don’t want to have more than one theme.

You can also get rid of app_root/images and app_root/css if you want that. It’s not used now.

Then you just use Yii::app()->theme->baseUrl ad libitum, because you’re using a theme, right?

If you have a layout in protected/views/layouts, then don’t use it there (obviously), because Yii is not using that when you’ve told it to apply your theme.

I hope I managed to indoctrinate you a bit. :)

I installed some themes in themes directory ("<site>/themes") and as I learned, I need to reference the theme in the main.php file in the “protected/config” directory. Is it right? I’m not sure how to do it.

I saw the main.php file in the theme define the menu that will be used instead of the menu defined in the config folder. Its ok and I’ve put the theme on.

But I have another question (I know it’s elementary): how can I put together, in the same page.php, two Mysql tables of type 1:n with one common index (idsuport). Thanks.

I was having an issue with this, a view reused across multiple themes with nothing different except for the css. If any changes are made each theme must be updated. While not a huge issue if you keep the same relative path to the css in each theme, I’d prefer to remove the duplication and hassle of replacing each view every time any change is made.

here’s the solution I came up with.


function registerCssFile($url, $media = '')

  {

    if(file_exists("css/".$url)) {

      parent::registerCssFile(Yii::app()->request->baseUrl."/css/".$url, $media);

      if(Yii::app()->theme && file_exists(Yii::app()->theme->basePath."/css/".$url))

        parent::registerCssFile(Yii::app()->theme->baseUrl."/css/".$url, $media);

    }

    else

      parent::registerCssFile($url, $media);

    return $this;

  }

I extend CClientScript and override this one method, adding functionality, but reverting to it’s default behavior if no file is found.

If found, the main css file is included unconditionally, with an optional theme specific one, allowing less duplication of code since most of my themes are very similarly laid out with only a few small overwritten rules.

i am applying blackboot theme to my application but css is not working properly when i go to manage page of any view.

your css file put in the file

themes/your theme/views/layout/main.php

then call all css file like this

<link href="<?php echo Yii::app()->theme->baseUrl;?>/css/style.css" rel="stylesheet" media="screen" title="default">

<link href="<?php echo Yii::app()->theme->baseUrl;?>/css/slidebars.css" rel="stylesheet" media="screen">

<link href="<?php echo Yii::app()->theme->baseUrl;?>/css/bootstrap.css" rel="stylesheet" media="screen">

etc…

its working fine…

I hate duplicating code, so by default my themes rely on the standard implementation (layouts, …) and only on the theme implementation if it exists.

For views, yii will effectively look in the theme directory first, however as suggested above, Yii does not do that for Css files.

Therefore I developped my own Utility functions to look for theme resources (css, images, …).


class Utils {


    /**

 	* Gets the theme Url for the resource if it exists, and the default Url otherwise.

 	*

 	* @param string $relativepath Relative path to the url and the base and theme paths.

 	* @return string

 	*/

    public static function getThemeOrStdUrl($relativepath,$default=null) {

        $theme = Yii::app()->theme;

        //print empty($theme)?"no theme":"has theme ".$theme->getBasePath();

        //print "File ".$theme->getBasePath().DIRECTORY_SEPARATOR.$relativepath."\n";

        if(!empty($theme) && file_exists($theme->getBasePath().DIRECTORY_SEPARATOR.$relativepath)) {

            //print "\nTheme ".$theme->getBaseUrl()."/".$relativepath."\n";

            return $theme->getBaseUrl()."/".$relativepath;

        } elseif($default===null||file_exists(dirname(Yii::app()->getRequest()->getScriptFile()).DIRECTORY_SEPARATOR.$relativepath)) {

            //print "\nBase ".Yii::app()->getBaseUrl()."/".$relativepath."\n";

            return Yii::app()->getBaseUrl()."/".$relativepath;

        } else {

            return $default;

        }

    }


    /**

 	* Gets the theme path (not url) for the resource if it exists, and the default path otherwise.

 	*

 	* @param string $relativepath Relative path the base and theme paths.

 	* @return string

 	*/

    public static function getThemeOrStdPath($relativepath) {

    	$theme = Yii::app()->theme;

    	if(!empty($theme) && file_exists($theme->getBasePath().DIRECTORY_SEPARATOR.$relativepath)) {

        	return $theme->getBasePath().DIRECTORY_SEPARATOR.$relativepath;

    	} else {

    		return Yii::app()->getBasePath()."/".$relativepath;

    	}

    }


}

and this is used like this:


Yii::app()->clientScript->registerCssFile(Utils::getThemeOrStdUrl('/css/main.css'));

Yii::app()->clientScript->registerCssFile(Utils::getThemeOrStdUrl('/css/form.css'));

Yii::app()->clientScript->registerCssFile(Utils::getThemeOrStdUrl('/css/admin.css'));




echo CHtml::image(Utils::getThemeOrStdUrl(Yii::t('app','ico.addalert')),[/size]



As you can see, I also reference image paths through a translation so that I can adjust the image using the internationalisation methods. For that I have changed CPhpMessageSource - I just created a wikifor that after reading this post