原文链接:http://www.fancyecommerce.com/2016/05/28/yii2-页面功能块(前端后端提供数据类),以及深度/
在用yii2做大型网站的时候,尤其是做产品的时候,譬如做电商系统,在很多页面的侧栏,或者内容部分的底部等部分,我们希望通过配置的方式,很容易的把某个块加入,譬如在分类页面 显示客户的浏览产品记录 和 newsletter,在产品页面,我们同样想显示这些,我们可能做出来很多这样的显示独立块,让客户在后台通过配置的方式就可以加入这些块,我们需要考虑的如下
这些块由两部分组成,数据提供者block部分,view html部分,通过block提供的动态数据,画出整个页面。
当前功能块可能包含其他的功能块,也就是多个功能块嵌套。
实现上述功能,我们就可以做出来很多独立功能块,在各个页面很容易的配置。下面是实现的方法
我的yii2 fec扩展已经实现这个功能,github地址:https://github.com/fancyecommerce/yii2-fec
下面讲述的是实现原理。
这个是实现的原理文件:
<?php
namespace fec\helpers;
use Yii;
use yii\base\View;
use yii\base\InvalidConfigException;
class CView
{
# 功能块:
# 本功能的作用是通过一个类文件,和一个view 文件,生成一个html块,而且在这个html中还可以嵌套其他的块
# 这样设计的好处:譬如在前端,我们在很多url中都会有一些公用的侧栏块,我们很希望我们的块可以通过配置的方式很容易的加入到侧栏
# 譬如电商网站侧栏的:客户的浏览记录,我们在多个页面都想加入这个功能,我们就可以很方便的做加入。
# 默认的方法,功能块的提供数据的默认方法。可以在配置中配置method方法自定义。
const DATA_METHOD = 'getLastData';
/* 你可以在view 文件中通过下面的方式使用
<?php
use fec\helpers\CView;
$config = [
# 必填
'class' => 'fec\block\TestMenu',
'view' => '@fec/views/testmenu/index.php',
# 下面为选填
'method'=> 'getLastData',
'terry1'=> 'My1',
'terry2'=> 'My2',
];
echo CView::getChildHtml($config)
?>
*/
public static function getChildHtml($config)
{
if(!isset($config['class']) || empty($config['class'])
|| !isset($config['view']) || empty($config['view'])
){
throw new InvalidConfigException('view and class must exist in array config!');
}
$method = self::DATA_METHOD;
if(isset($config['method']) && !empty($config['method'])){
$method = $config['method'];
unset($config['method']);
}
$view = $config['view'];
unset($config['view']);
$ob = Yii::createObject($config);
$params = $ob->$method();
return Yii::$app->view->render($view, $params);
}
# 通过配置
/*
1.add config param to modules params or application params.
params.php
[
'params' => [
'block' =>[
'menu' =>[
# 必填
'class' => 'fec\block\TestMenu',
'view' => '@fec/views/testmenu/index.php',
# 下面为选填
'method'=> 'getLastData',
'terry1'=> 'My1',
'terry2'=> 'My2',
],
]
]
]
2.
use fec\helpers\CView;
CView::getConfigChildHtml('menu');
*/
public static function getConfigChildHtml($configKey){
$config = [];
# get config from module param
if($module = Yii::$app->controller->module){
$module_config = CModule::param("block");
if(isset($module_config[$configKey])){
$config = $module_config[$configKey];
}
}
# if module config param is empty or not exist,
# get config from application
if(empty($config)){
$app_config = CConfig::param("block");
if(isset($app_config[$configKey])){
$config = $app_config[$configKey];
}
}
if(!isset($config['class']) || empty($config['class'])
|| !isset($config['view']) || empty($config['view'])
){
throw new InvalidConfigException('view and class must exist in array config!');
}else{
return self::getChildHtml($config);
}
}
}
2.新建功能块的block文件:
<?php
namespace fec\block;
use Yii;
class TestMenu
{
public $terry1;
public $terry2;
public function getLastData()
{
$arr = [
'terry1' =>$this->terry1,
'terry2' =>$this->terry2,
];
return $arr;
}
}
3.新建view显示部分:
<div>My Name is
<?php
echo $terry1."_".$terry2;
?>
</div>
4.在其他的view文件中调用:
<?php
use fec\helpers\CView;
$config = [
'class' => 'fec\block\TestMenu',
'view' => '@fec/views/testmenu/index.php',
# 下面为选填
'method'=> 'getLastData',
'terry1'=> 'My111',
'terry2'=> 'My222',
];
echo CView::getChildHtml($config);
?>
也就是通过上面的配置数组指定block的提供者, view文件的实现文件,也就是上面的步骤 2 和3,method为选填,如果不填写,默认为getLastData函数,terry1,terry2为初始化提供变量,然后我们就可以看到输出了
My Name is My111_My222
5.我们通过配置的方式调用CView::getConfigChildHtml()函数
5.1 加入module配置:(在report 配置中)
<?php
return [
'report' => [
'class' => 'appadmin\code\Report\Module',
'components'=>[
'mycomponent' => [
'class' => 'appadmin\component\MyComponent',
'terry' => 'xxxx',
],
],
'params' => [
'water' => 'good',
'block' =>[
'menu' =>[
# 必填
'class' => 'fec\block\TestMenu',
'view' => '@fec/views/testmenu/index.php',
# 下面为选填
'method'=> 'getLastData',
'terry1'=> 'My1',
'terry2'=> 'My2',
],
]
],
],
];
当然,您如果不使用模块,可以在params.php中直接加入block的配置部分:
'params' => [
'water' => 'good',
'block' =>[
'menu' =>[
# 必填
'class' => 'fec\block\TestMenu',
'view' => '@fec/views/testmenu/index.php',
# 下面为选填
'method'=> 'getLastData',
'terry1'=> 'My1',
'terry2'=> 'My2',
],
]
],
如果application 和module同时配置,那么在当前module下面,module下面的配置有限,
使用:
<?php
use fec\helpers\CView;
echo CView::getConfigChildHtml('menu')
?>
结果:
My Name is My1_My2
总结:这个功能是可以深度嵌套,譬如在view1.php调用了child -> menu,
在menu的view文件中又调用了child–>product ,…..,深入嵌套,这是魅力所在。
本文由 fecommerce 创作,采用 知识共享署名 3.0 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。
微信