fecshop 使用了多模板view文件优先级加载,在view和layout文件比较容易解决
比较难弄的是js和css部分,用yii2提供的yii\web\AssetBundle; 做了很多尝试都没有解决,最后自己写了一个来最终实现多模板下 js和css,也根据模板路径优先级下载。
首先说一下多模板路径,下面有多个模板路径,按照优先级依次如下:
@appfront/theme/terry/theme01/
@fecshop/theme/base/front/
@fecshop/theme/base/base/
如果我要加载的view文件为 cms/index/index, 首先查看 @appfront/theme/terry/theme01/cms/index/index.php文件是否存在,如果不存在,则查看@fecshop/theme/base/front/cms/index/index.php,如果还不存在,则看文件@fecshop/theme/base/base/cms/index/index.php 是否存在,如果不存在则报错返回。
上面是多模板的思路,为了是解决view文件,在fecshop系统模板升级和用户二次开发模板的矛盾冲突。
现在我想要css和js也这样,通过优先级加载css和js,
下面是我的实现:定义组件配置 :
'asset' => [ 'class' => 'fecshop\services\page\Asset', # js config 'jsOptions' => [ # js config 1 [ 'options' => [ 'position' => 'POS_END', // 'condition'=> 'lt IE 9', ], 'js' =>[ 'js/jquery-3.0.0.min.js', 'js/js.js', ], ], # js config 2 [ 'options' => [ 'condition'=> 'lt IE 9', ], 'js' =>[ 'js/ie9js.js' ], ], ], # css config 'cssOptions' => [ # css config 1. [ 'css' =>[ 'css/style.css', 'css/ie.css', ], ], # css config 2. [ 'options' => [ 'condition'=> 'lt IE 9', ], 'css' =>[ 'css/ltie9.css', ], ], ], //'cssOptions' => [ // 'condition' //], //'jsOptions' => [ // 'position' => 'POS_END', //] ],
2. 组件部分:
<?php /** * FecShop file. * * @link http://www.fecshop.com/ * @copyright Copyright (c) 2016 FecShop Software LLC * @license http://www.fecshop.com/license/ */ namespace fecshop\services\page; use Yii; use yii\base\Component; use yii\helpers\ArrayHelper; use yii\helpers\Url; /** * Breadcrumbs services * @author Terry Zhao <2358269014@qq.com> * @since 1.0 extends AssetBundle */ class Asset extends Component { public $cssOptions; public $jsOptions; /** * 在模板路径下的相对文件夹。 * 譬如模板路径为@fecshop/app/theme/base/front * 那么js,css路径默认为@fecshop/app/theme/base/front/assets */ public $defaultDir = 'assets'; /** * 文件路径默认放到模板路径下面的assets里面 */ public function register($view){ $assetArr = []; $themeDir = Yii::$app->page->theme->getThemeDirArr(); if( is_array($themeDir) && !empty($themeDir)){ if( is_array($this->jsOptions) && !empty($this->jsOptions)){ foreach($this->jsOptions as $jsOption){ if( isset($jsOption['js']) && is_array($jsOption['js']) && !empty($jsOption['js'])){ foreach($jsOption['js'] as $jsPath){ foreach($themeDir as $dir){ $dir = $dir.'/'.$this->defaultDir.'/'; $jsAbsoluteDir = $dir.$jsPath; if(file_exists($jsAbsoluteDir)){ $assetArr[$dir]['jsOptions'][] = [ 'js' => $jsPath, 'options' => $this->initOptions($jsOption['options']), ]; break; } } } } } } if( is_array($this->cssOptions) && !empty($this->cssOptions)){ foreach($this->cssOptions as $cssOption){ if( isset($cssOption['css']) && is_array($cssOption['css']) && !empty($cssOption['css'])){ foreach($cssOption['css'] as $cssPath){ foreach($themeDir as $dir){ $dir = $dir.'/'.$this->defaultDir.'/'; $cssAbsoluteDir = $dir.$cssPath; if(file_exists($cssAbsoluteDir)){ $assetArr[$dir]['cssOptions'][] = [ 'css' => $cssPath, 'options' => $this->initOptions($cssOption['options']), ]; break; } } } } } } } if(!empty($assetArr)){ foreach($assetArr as $fileDir=>$as){ $cssConfig = $as['cssOptions']; $jsConfig = $as['jsOptions']; $publishDir = $view->assetManager->publish($fileDir); if(!empty($jsConfig) && is_array($jsConfig)){ foreach($jsConfig as $c){ $view->registerJsFile($publishDir[1].'/'.$c['js'],$c['options']); } } if(!empty($cssConfig) && is_array($cssConfig)){ foreach($cssConfig as $c){ $view->registerCssFile($publishDir[1].'/'.$c['css'],$c['options']); } } } } } public function initOptions($options){ if(isset($options['position'])){ if($options['position'] == 'POS_HEAD'){ $options['position'] = \yii\web\View::POS_HEAD; }else if($options['position'] == 'POS_END'){ $options['position'] = \yii\web\View::POS_END; } } return $options; } }
上面的 Yii::$app->page->theme->getThemeDirArr() 表示得到多模板路径数组。
在layout文件中使用
\Yii::$app->page->asset->register($this);
经过测试,可以在多个模板路径的assets下面查找js,找到后返回,找不到,继续到下一个模板路径中找js或者css文件。最后发布。