yii2 页面功能块配置实现原理,以及views深度嵌套

技巧库 · fecommerce · 于 7年前 发布 · 5826 次阅读

原文链接: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 中国大陆许可协议 进行许可。 可自由转载、引用,但需署名作者且注明文章出处。


微信

本帖已被设为精华帖!
共收到 0 条回复 yii2 view 嵌套
没有找到数据。
添加回复 (需要登录)
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册