Yii 主題核心概念
- 主題目錄:`@webroot/themes/主題名/`
- 視圖覆蓋規則:`views/ControllerID/ActionID.php` → `themes/主題名/views/ControllerID/ActionID.php`
- 佈局文件:`views/layouts/main.php` → `themes/主題名/views/layouts/main.php`
- 資源文件:CSS/JS/圖片放在主題目錄下,通過 `$this->theme->baseUrl` 引用
目錄結構示例
webroot/
├── themes/
│ ├── cyan/ # 主題一:青色
│ │ ├── views/
│ │ │ ├── layouts/
│ │ │ │ └── main.php
│ │ │ ├── site/
│ │ │ │ └── index.php
│ │ │ └── post/
│ │ │ └── create.php
│ │ ├── css/
│ │ │ ├── main.css
│ │ │ ├── form.css
│ │ │ └── screen.css
│ │ └── images/
│ │ └── logo.png
│ └── grey/ # 主題二:灰色
│ └── (同結構)
├── protected/
│ └── views/ # 默認視圖(被主題覆蓋)
└── css/ # 默認資源(被主題覆蓋)
配置啟用主題
<?php
// protected/config/main.php
return [
'components' => [
'themeManager' => [
'basePath' => '@webroot/themes', // 可自定義
'baseUrl' => '@web/themes',
],
],
// 方式一:配置文件固定主題
'theme' => 'cyan',
// 方式二:動態切換(在控制器/動作中)
// Yii::app()->theme = 'grey';
];
主題佈局文件:動態引用主題資源
<?php
// themes/cyan/views/layouts/main.php
<!DOCTYPE html>
<html xmlns="https://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="language" content="en" />
<!-- 關鍵:使用 theme->baseUrl 引用主題內資源 -->
<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->theme->baseUrl; ?>/css/screen.css"
media="screen, projection" />
<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->theme->baseUrl; ?>/css/print.css"
media="print" />
<!--[if lt IE 8]>
<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->theme->baseUrl; ?>/css/ie.css"
media="screen, projection" />
<![endif]-->
<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->theme->baseUrl; ?>/css/main.css" />
<link rel="stylesheet" type="text/css"
href="<?php echo Yii::app()->theme->baseUrl; ?>/css/form.css" />
<title><?php echo Yii::app()->name . ' - ' . Yii::app()->theme->name; ?></title>
</head>
<body>
<h1>Current Theme: <?php echo Yii::app()->theme->name; ?></h1>
<?php echo $content; ?>
</body>
</html>
主題 CSS 差異化示例
<!-- themes/cyan/css/main.css -->
body { background: #00FFFF; color: #333; }
<!-- themes/grey/css/main.css -->
body { background: #CCCCCC; color: #333; }
模塊控制器視圖覆蓋規則
// 控制器:forum/modules/PostController
// 默認視圖:protected/views/forum/post/create.php
// 主題視圖:themes/cyan/views/forum/post/create.php
// 巢狀模塊:support/modules/forum/PostController
// 主題視圖:themes/cyan/views/support/forum/post/create.php
動態切換主題控制器示例
<?php
class ThemeController extends CController
{
public function actionSwitch($theme)
{
$allowed = ['cyan', 'grey', 'dark', 'light'];
if (in_array($theme, $allowed)) {
Yii::app()->theme = $theme;
// 可存入 Session/Cookie 持久化
Yii::app()->user->setState('theme', $theme);
}
$this->redirect(Yii::app()->request->urlReferrer);
}
public function actionAuto()
{
// 根據時間自動切換
$hour = (int)date('H');
$theme = ($hour >= 6 && $hour < 18) ? 'light' : 'dark';
Yii::app()->theme = $theme;
$this->redirect(Yii::app()->request->urlReferrer);
}
}
?>
主題資源引用最佳實踐
| 資源類型 | 引用方式 | 示例 |
| CSS | link 標籤 + baseUrl | `Yii::app()->theme->baseUrl . '/css/main.css'` |
| JavaScript | script 標籤 + baseUrl | `Yii::app()->theme->baseUrl . '/js/app.js'` |
| 圖片 | img 標籤 + baseUrl | `Yii::app()->theme->baseUrl . '/images/logo.png'` |
| 背景圖 | CSS 內 url() | `background: url(images/bg.png)` 相對 CSS 文件 |
主題繼承與擴展
<?php
// 基礎主題:basic
// 擴展主題:premium (繼承 basic 並覆蓋部分文件)
// 配置
'themeManager' => [
'basePath' => '@webroot/themes',
],
'theme' => 'premium',
// 文件查找順序:
// 1. themes/premium/views/Controller/action.php
// 2. themes/basic/views/Controller/action.php (父主題)
// 3. protected/views/Controller/action.php (默認視圖)
?>
常見問題排查
| 問題 | 原因 | 解決 |
| 主題不生效 | 大小寫不匹配 | Linux 區分大小寫,目錄名必須與 theme 值完全一致 |
| CSS/JS 404 | baseUrl 路徑錯誤 | 檢查 themeManager.baseUrl 配置,確保 Web 可訪問 |
| 視圖未覆蓋 | 目錄結構錯誤 | 嚴格遵循 views/ControllerID/ActionID.php 結構 |
| 模塊視圖不覆蓋 | 模塊 ID 路徑缺失 | 主題下建立 views/ModuleID/ControllerID/ActionID.php |
Yii 主題機制通過「約定優於配置」實現視圖與資源的徹底分離,是多皮膚、白標產品、A/B 測試的利器。