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文件。最后发布。