Темы оформления =============== Темы оформления являются традиционным способом настроить внешний вид страниц веб-приложения. Применив новую тему, мы можем изменить внешний вид всего приложения за считанные секунды. В 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] array( 'nextPageLabel'=>'next', 'prevPageLabel'=>'prev', ), 'classic'=>array( 'header'=>'', 'maxButtonCount'=>5, ), ); ~~~ В коде выше мы создаём для виджета [CLinkPager] два скина: `default` и `classic`. Первый скин будет применяться к любому виджету [CLinkPager], в котором явно не указано свойство `skin`, а второй — к виджету, свойство `skin` которого имеет значение `classic`. Например, в следующем коде представления первым виджет будет использовать скин `default`, а второй — скин `classic`: ~~~ [php] widget('CLinkPager'); ?> widget('CLinkPager', array('skin'=>'classic')); ?> ~~~ Если мы создаём виджет с набором первоначальных значений, они будут иметь приоритет и будут объединены с любыми применяемыми скинами. Например, следующий код представления создаст постраничную разбивку, чьи первоначальные значения — это массив `array('header'=>'', 'maxButtonCount'=>6, 'cssFile'=>false)`, который является результатом слияния первоначальных значений, указанных в представлении, и скина `classic`. ~~~ [php] widget('CLinkPager', array( 'skin'=>'classic', 'maxButtonCount'=>6, 'cssFile'=>false, )); ?> ~~~ Заметим, что скинизация НЕ требует использования темы. Однако, если тема активна, Yii также будет искать скины в директории `skins` представлений темы (например, `WebRoot/themes/classic/views/skins`). В случае, если скин с таким же именем существует и в директории представления темы и в основной директории представления приложения, скин темы будет иметь приоритет. Если виджет использует несуществующий скин, Yii по-прежнему будет создавать виджет как обычно, без каких-либо ошибок. > Info|Информация: Использование скина может привести к снижению производительности, поскольку Yii должен найти файл скина, когда виджет создается впервые. Использование скинов очень похоже на глобальную конфигурацию виджетов. Главные отличия следующие: - Скины в большей степени относятся к изменению свойств, отвечающих за внешний вид виджета; - У виджета может быть несколько скинов; - Скин можно темизировать; - Использование скинов более затратно, чем использование глобальной конфигурации.