Also available in these languages:
DeutschEnglishEspañolFrançaisBahasa Indonesia日本語polskiPortuguêsRomâniaРусскийsvenska简体中文

Theming

Theming is a systematic way of customizing the outlook of pages in a Web application. By applying a new theme, the overall appearance of a Web application can be changed instantly and dramatically.

In Yii, each theme is represented as a directory consisting of view files, layout files, and relevant resource files such as images, CSS files, JavaScript files, etc. The name of a theme is its directory name. All themes reside under the same directory WebRoot/themes. At any time, only one theme can be active.

Tip: The default theme root directory WebRoot/themes can be configured to be a different one. Simply configure the basePath and the baseUrl properties of the themeManager application component to be the desired ones.

To activate a theme, set the theme property of the Web application to be the name of the desired theme. This can be done either in the application configuration or during runtime in controller actions.

Note: Theme name is case-sensitive. If you attempt to activate a theme that does not exist, Yii::app()->theme will return null.

Contents under a theme directory should be organized in the same way as those under the application base path. For example, all view files must be located under views, layout view files under views/layouts, and system view files under views/system. For example, if we want to replace the create view of PostController with a view in the classic theme, we should save the new view file as WebRoot/themes/classic/views/post/create.php.

For views belonging to controllers in a module, the corresponding themed view files should also be placed under the views directory. For example, if the aforementioned PostController is in a module named forum, we should save the create view file as WebRoot/themes/classic/views/forum/post/create.php. If the forum module is nested in another module named support, then the view file should be WebRoot/themes/classic/views/support/forum/post/create.php.

Note: Because the views directory may contain security-sensitive data, it should be configured to prevent from being accessed by Web users.

When we call render or renderPartial to display a view, the corresponding view file as well as the layout file will be looked for in the currently active theme. And if found, those files will be rendered. Otherwise, it falls back to the default location as specified by viewPath and layoutPath.

Tip: Inside a theme view, we often need to link other theme resource files. For example, we may want to show an image file under the theme's images directory. Using the baseUrl property of the currently active theme, we can generate the URL for the image as follows,

Yii::app()->theme->baseUrl . '/images/FileName.gif'

Below is an example of directory organization for an application with two themes basic and fancy.

WebRoot/
    assets
    protected/
        .htaccess
        components/
        controllers/
        models/
        views/
            layouts/
                main.php
            site/
                index.php
    themes/
        basic/
            views/
                .htaccess
                layouts/
                    main.php
                site/
                    index.php
        fancy/
            views/
                .htaccess
                layouts/
                    main.php
                site/
                    index.php

In the application configuration, if we configure

return array(
    'theme'=>'basic',
    ......
);

then the basic theme will be in effect, which means the application's layout will use the one under the directory themes/basic/views/layouts, and the site's index view will use the one under themes/basic/views/site. In case a view file is not found in the theme, it will fall back to the one under the protected/views directory.

Skin

Note: The skin feature has been available since version 1.1.0.

While using a theme we can quickly change the outlook of views, we can use skins to systematically customize the outlook of the widgets used in the views.

A skin is an array of name-value pairs that can be used to initialize the properties of a widget. A skin belongs to a widget class, and a widget class can have multiple skins identified by their names. For example, we can have a skin for the CLinkPager widget and the skin is named as classic.

In order to use the skin feature, we first need to modify the application configuration by installing the widgetFactory component:

return array(
    'components'=>array(
        'widgetFactory'=>array(
            'class'=>'CWidgetFactory',
        ),
    ),
);

We then create the needed skins. Skins belonging to the same widget class are stored in a single PHP script file whose name is the widget class name. All these skin files are stored under protected/views/skins, by default. If you want to change this to be a different directory, you may configure the skinPath property of the widgetFactory component. As an example, we may create under protected/views/skins a file named CLinkPager.php whose content is as follows,

<?php
return array(
    'default'=>array(
        'nextPageLabel'=>'&gt;&gt;',
        'prevPageLabel'=>'&lt;&lt;',
    ),
    'classic'=>array(
        'header'=>'',
        'maxButtonCount'=>5,
    ),
);

In the above, we create two skins for the CLinkPager widget: default and classic. The former is the skin that will be applied to any CLinkPager widget that we do not explicitly specify its skin property, while the latter is the skin to be applied to a CLinkPager widget whose skin property is specified as classic. For example, in the following view code, the first pager will use the default skin while the second the classic skin:

<?php $this->widget('CLinkPager'); ?>
 
<?php $this->widget('CLinkPager', array('skin'=>'classic')); ?>

If we create a widget with a set of initial property values, they will take precedence and be merged with any applicable skin. For example, the following view code will create a pager whose initial values will be array('header'=>'', 'maxButtonCount'=>6, 'cssFile'=>false), which is the result of merging the initial property values specified in the view and the classic skin.

<?php $this->widget('CLinkPager', array(
    'skin'=>'classic',
    'maxButtonCount'=>6,
    'cssFile'=>false,
)); ?>

Note that the skin feature does NOT require using themes. However, when a theme is active, Yii will also look for skins under the skins directory of the theme's view directory (e.g. WebRoot/themes/classic/views/skins). In case a skin with the same name exists in both the theme and the main application view directories, the theme skin will take precedence.

If a widget is using a skin that does not exist, Yii will still create the widget as usual without any error.

Info: Using skin may degrade the performance because Yii needs to look for the skin file the first time a widget is being created.

$Id: topics.theming.txt 1463 2009-10-17 01:49:02Z qiang.xue $
If you found any typos or errors in the tutorial, please create a Yii ticket to report it. If it is a translation error, please create a Yiidoc ticket, instead. Thank you.

Total 1 comment:

#1262
system view files
by webscriptz at 3:09pm on March 11, 2010.

What can be defined as system view files?

and how can i compile a layout from multiple subfiles? if i have two different layout for the same themes depending on the module used?

Your Comment:

You may enter comment using Markdown syntax.

Please login with your forum account.
Note: you must have at least ONE forum post with your account.