Yii 的 Assets(資源發布)機制解決了模塊/擴展內部靜態資源(CSS、JS、圖片)無法直接被 Web 訪問的問題。本文深入剖析原理、配置與最佳實踐。
protected/ 目錄默認禁止 Web 直接訪問,但模塊開發時需要將其下的 assets/ 靜態資源對外可用。CAssetManager::publish() 將指定源目錄複製到 webroot/assets/<hash>/,生成唯一隨機哈希目錄名,避免命名衝突與瀏覽器緩存失效。CClientScript 註冊 CSS/JS,自動處理依賴順序與去重。<?php
// 在控制器或視圖中
$assets = Yii::getPathOfAlias('ext.css'); // 源目錄
$baseUrl = Yii::app()->assetManager->publish($assets); // 發布並獲取公開 URL
Yii::app()->clientScript->registerCssFile($baseUrl.'/main.css'); // 註冊 CSS
?>
以 admin 模塊為例,在 AdminModule.php 中封裝資源 URL 獲取:
<?php
class AdminModule extends CWebModule {
private $_assetsUrl;
public function getAssetsUrl() {
if ($this->_assetsUrl === null) {
$this->_assetsUrl = Yii::app()->getAssetManager()->publish(
Yii::getPathOfAlias('application.modules.admin.assets')
);
}
return $this->_assetsUrl;
}
public function setAssetsUrl($value) { $this->_assetsUrl = $value; }
}
?>
視圖布局文件 views/layouts/main.php 中調用:
<link rel="stylesheet" type="text/css" href="<?php echo $this->module->assetsUrl; ?>/css/screen.css" />
YII_DEBUG 強制重新複製:
$baseUrl = Yii::app()->assetManager->publish($path, false, -1, YII_DEBUG);
publish($path, $hashByName, $level, $forceCopy)
$hashByName:是否按源路徑哈希命名目錄(true 固定目錄名,false 隨機)。$level:遞歸複製深度(-1 全部,0 僅文件,>0 指定層級)。$forceCopy:強制覆蓋已發布文件(調試設 true,生產 false)。Yii::app()->assetManager->clearAll() 或手動刪除 webroot/assets/ 下舊目錄。webroot/assets/ 目錄可寫(Linux 下 chmod 777 或屬于 Web 用戶)。Yii::getPathOfAlias() 參數需與 config/main.php 中 aliases 配置一致。main.css),發布後哈希目錄雖隔離,但註冊時若無命名空間前綴,clientScript 可能去重導致樣式缺失。建議文件名加模塊前綴(admin-main.css)。YII_DEBUG,啟用 assetManager->linkAssets = true(符號鏈接而非複製,需文件系統支持),配合前端構建工具(Webpack/Vite)預編譯壓縮,減少發布開銷。