Темы оформления
===============

Темы оформления являются традиционным способом настроить внешний вид страниц веб-приложения. Применив новую тему,
мы можем изменить внешний вид всего приложения за считанные секунды.

В Yii каждая тема представлена как папка, содержащая файлы представлений, макетов и прочих необходимых файлов, таких,
как CSS, JavaScript и пр. Название папки соответственно определяет название темы. Все темы хранятся в папке
`WebRoot/themes`, при этом быть активной, т.е. использоваться в текущий момент, может только одна из тем.

> Tip|Подсказка: Папку, где по умолчанию хранятся темы — `WebRoot/themes` — можно легко изменить путем
установки свойств [basePath|CThemeManager::basePath] и [baseUrl|CThemeManager::baseUrl]
компонента [themeManager|CWebApplication::themeManager] на желаемые.

Использование темы
------------------

Для активации темы нужно установить значение [theme|CWebApplication::theme] равным имени соответствующей темы.
Это можно проделать	 путем [конфигурации приложения](/doc/guide/basics.application#application-configuration) или
прямо в ходе выполнения в действиях контроллера.

> Note|Примечание: Имя темы чувствительно к регистру, и, если попытаться активировать несуществующую тему, свойство
 `Yii::app()->theme` вернет `null`.


Создание темы
-------------

Содержимое папки с темами должно быть организовано точно так же, как и содержимое [базовой директории приложения](/doc/guide/basics.application#application-base-directory), то есть, все файлы представлений
должны находиться в папке `views`, макеты представлений в папке `views/layouts`, а файлы системных представлений
в папке `views/system`. Например, если необходимо заменить представление `create` контроллера `PostController` на
представление темы `classic`, нужно сохранить новый файл представления как `WebRoot/themes/classic/views/post/create.php`.

Для представлений контроллеров в [модулях](/doc/guide/basics.module), соответствующие файлы оформленных представлений нужно
также поместить в папку `views`. Например, если упомянутый выше контроллер `PostController` входит в модуль `forum`, необходимо
сохранить файл представления `create` как `WebRoot/themes/classic/views/forum/post/create.php`. Если модуль `forum` является
составной частью другого модуля `support`, то файл представления должен быть сохранен как `WebRoot/themes/classic/views/support/forum/post/create.php`.

> Note|Примечание: Папка `views` может содержать данные чувствительные с точки зрения безопасности, поэтому необходимо
ограничить доступ к папке извне сервера.

В момент вызова метода [render|CController::render] или [renderPartial|CController::renderPartial] для отображения
представления происходит обращение к соответствующим файлам представлений и макетов активной темы. Если файлы найдены, начнется
формирование странички, в противном случае, будут использоваться файлы оформления по умолчанию, месторасположение
которых устанавливается свойствами [viewPath|CController::viewPath] и [layoutPath|CWebApplication::layoutPath].

> Tip|Подсказка: Часто в представлениях темы приходится ссылаться на прочие файлы темы, например, для отображения
> картинки, находящейся в подпапке темы `images`. Используя свойство [baseUrl|CTheme::baseUrl] активной темы, можно
> сформировать корректную ссылку на картинку следующим образом:
> ~~~
> [php]
> Yii::app()->theme->baseUrl . '/images/FileName.gif'
> ~~~

Ниже приведён пример организации директорий приложения с двумя темами `basic` и `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
~~~

В настройках приложения, если мы будем использовать:

~~~
[php]
return array(
	'theme'=>'basic',
	…
);
~~~

то будет применяться тема `basic`. То есть главный макет (layout) будет браться из
`themes/basic/views/layouts`, а представление index — из `themes/basic/views/site`.
Если файл представления не найден в теме, будет использован файл из
`protected/views`.


Темизация виджетов
------------------

Начиная с версии 1.1.5, отображения, используемые в виджетах, можно темизировать.
При вызове [CWidget::render()] для вывода отображения, Yii сделает попытку найти
его в темах перед тем, как загрузить из директории виджета.

Для темизации отображения `xyz` виджета с именем класса `Foo`, необходимо создать
директорию `Foo` (с тем же именем, что и у класса) внутри директории с отображениями
активной темы. Если класс виджета находится в пространстве имён (начиная с PHP 5.3.0),
таком как `\app\widgets\Foo`, то необходимо создать директорию `app_widgets_Foo`.
В имени мы заменяем разделители пространства имён на подчёркивание.

После этого создаём файл отображения `xyz.php` в только что добавленной директории.
К этому моменту мы имеем файл `themes/basic/views/Foo/xyz.php`, который и будет использоваться
виджетом вместо его собственного отображения, если активная тема — `basic`.


Глобальная настройка виджетов
-----------------------------

> Note|Примечание: данная возможность доступна с версии 1.1.3.

При использовании виджета, как стандартного, так и стороннего, часто требуется
его настройка. К примеру, может понадобиться изменить значение
[CLinkPager::maxButtonCount] с 10 (по умолчанию) на 5. Мы можем сделать это,
передав начальные значения при вызове [CBaseController::widget] для создания
виджета. Тем не менее, делать это везде, где мы используем [CLinkPager] довольно
неудобно.

~~~
[php]
$this->widget('CLinkPager', array(
	'pages'=>$pagination,
    'maxButtonCount'=>5,
    'cssFile'=>false,
));
~~~

При использовании глобальной настройки, необходимо указать начальные значения
лишь в одном месте — в файле конфигурации приложения. Для этого настраиваем
[widgetFactory|CWebApplication::widgetFactory] следующим образом:

~~~
[php]
return array(
    'components'=>array(
        'widgetFactory'=>array(
            'widgets'=>array(
                'CLinkPager'=>array(
                    'maxButtonCount'=>5,
                    'cssFile'=>false,
                ),
                'CJuiDatePicker'=>array(
                    'language'=>'ru',
                ),
            ),
        ),
    ),
);
~~~

Выше мы указали глобальные настройки виджетов [CLinkPager] и [CJuiDatePicker]
при помощи соответствующих свойств [CWidgetFactory::widgets]. Стоит отметить, что
глобальные настройки указываются в виде пар ключ-массив значений, где
ключ соответствует классу виджета, а массив значений задаёт начальные значения
свойств этого класса.

Теперь всякий раз, когда мы используем виджет [CLinkPager] в отображении,
его свойствам будут присвоены указанные выше начальные значения. Таким образом,
чтобы использовать виджет будет достаточно следующего кода:

~~~
[php]
$this->widget('CLinkPager', array(
	'pages'=>$pagination,
));
~~~

Мы можем переопределить начальные значения, если в этом есть необходимость.
К примеру, если в каком-нибудь отображении мы хотим задать `maxButtonCount`
равным 2, можно сделать следующее:

~~~
[php]
$this->widget('CLinkPager', array(
	'pages'=>$pagination,
	'maxButtonCount'=>2,
));
~~~


Скины
-----

В то время, как при использовании темы мы можем быстро менять вид
представлений, мы также можем использовать скины для настройки вида
[виджетов](/doc/guide/basics.view#widget), используемых в представлениях.

Скин — это массив пар имя-значение, который может использоваться для
инициализации свойств виджета. Скин принадлежит классу виджета, а класс виджета
может иметь несколько скинов, идентифицируемых по имени. Например, у нас может
быть скин `classic` для виджета [CLinkPager].

Для использования данной возможности нам, в первую очередь, необходимо изменить
файл конфигурации приложения, выставив свойство [CWidgetFactory::enableSkin]
компонента `widgetFactory` в true:

~~~
[php]
return array(
    'components'=>array(
        'widgetFactory'=>array(
            'enableSkin'=>true,
        ),
    ),
);
~~~

В версиях Yii до 1.1.3 необходимо использовать следующую конфигурацию:

~~~
[php]
return array(
    'components'=>array(
        'widgetFactory'=>array(
            'class'=>'CWidgetFactory',
        ),
    ),
);
~~~


Затем мы создаём необходимые скины. Скины, принадлежащие одному классу виджета,
хранятся в одном файле PHP, имя которого совпадает с названием класса виджета.
Все файлы скинов по умолчанию хранятся в директории `protected/views/skins`. Для
изменения директории надо настроить свойство `skinPath` компонента
`widgetFactory`. Например, мы можем создать в директории
`protected/views/skins` файл `CLinkPager.php`, код которого представлен ниже:

~~~
[php]
<?php
return array(
    'default'=>array(
        'nextPageLabel'=>'next',
        'prevPageLabel'=>'prev',
    ),
    'classic'=>array(
        'header'=>'',
        'maxButtonCount'=>5,
    ),
);
~~~

В коде выше мы создаём для виджета [CLinkPager] два скина: `default` и
`classic`. Первый скин будет применяться к любому виджету [CLinkPager], в
котором явно не указано свойство `skin`, а второй — к виджету, свойство `skin`
которого имеет значение `classic`. Например, в следующем коде представления
первым виджет будет использовать скин `default`, а второй — скин `classic`:

~~~
[php]
<?php $this->widget('CLinkPager'); ?>

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

Если мы создаём виджет с набором первоначальных значений, они будут
иметь приоритет и будут объединены с любыми применяемыми скинами. Например,
следующий код представления создаст постраничную разбивку, чьи первоначальные значения —
это массив `array('header'=>'', 'maxButtonCount'=>6, 'cssFile'=>false)`,
который является результатом слияния первоначальных значений,
указанных в представлении, и скина `classic`.

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

Заметим, что скинизация НЕ требует использования темы. Однако, если тема
активна, Yii также будет искать скины в директории `skins` представлений темы
(например, `WebRoot/themes/classic/views/skins`). В случае, если скин с таким
же именем существует и в директории представления темы и в основной директории
представления приложения, скин темы будет иметь приоритет.

Если виджет использует несуществующий скин, Yii по-прежнему будет создавать виджет как обычно, без каких-либо ошибок.

> Info|Информация: Использование скина может привести к снижению производительности, поскольку Yii должен найти файл скина, когда виджет создается впервые.

Использование скинов очень похоже на глобальную конфигурацию виджетов. Главные
отличия следующие:

   - Скины в большей степени относятся к изменению свойств, отвечающих за внешний
     вид виджета;
   - У виджета может быть несколько скинов;
   - Скин можно темизировать;
   - Использование скинов более затратно, чем использование глобальной конфигурации.