1. 程式人生 > >[widget] -- yii2小部件高階使用

[widget] -- yii2小部件高階使用

原文連結 : http://blog.csdn.net/maclechan/article/details/46240183

(yii2.0高階應用)

注:以下佈局未使用iframe!

需求:在佈局中如何動態讀取選單欄資料?

最終效果如下:

說明:導航選單是寫進資料庫裡的,表nav 、navbar、navitem分別對應 一級/二級/三級選單欄 (當然你也可以只用一張表)如圖中的對應關係)。

導航資料是全域性都可訪問的,所以是不能寫進某個控制器裡面。因為又要使用佈局,一個比較好的解決方案就是使用小部件,這樣即可滿足佈局中可以動態讀取資料,還可以保證資料的全域性性。

一、佈局

如上圖,右側內容是可變的,所以除它外,所有內容都是放在backend/views/laouts下的

PHP檔案裡

頂部的一級選單欄和左側的選單欄分別放入兩個小部件中,然後在佈局中註冊使用兩個小部件即可。

為什麼要用小部件?   因為要保證資料的全域性性。

佈局程式碼如下(部分)

use backend\assets\AppAsset;  
use yii\helpers\Html;  
use yii\widgets\Breadcrumbs;  
  
/* @var $this \yii\web\View */  
/* @var $content string */  
  
//一級導航小部件  
use backend\components\NavWidget;  
//對應二三級導航小部件  
use backend\components\NavbarWidget;  
  
AppAsset::register($this);  
  
//略去n個字  
  
<!-- 一級導航小部件使用-->  
//這裡有一對php標籤把它包起來   NavWidget::widget()   
  
<div id="wrapper">  
      
    <!-- navbar對應二三級導航 -->   
       
          //把一級小部件裡面的導航id獲取到  
            $id = isset($_GET['id']) ? $_GET['id'] : 1;  
     
//把id傳到二三級小部件裡面<pre name="code" class="php">//這裡有一對php標籤把它包起來 NavbarWidget::widget(['id'=>$id])   
  
    <!--右側內容-->  
  // xxx  略去n個字  
佈局中使用小部件:
<?= NavWidget::widget() ?>
//傳參到小部件裡去
<?= NavbarWidget::widget(['id'=>$id,'en'=>$en]) ?>

二、建立小部件

backend下建立components/NavWidget.php

namespace backend\components;  
use backend\models\模型名;  
use yii\base\Widget;  
use yii\helpers\Html;  
  
class NavWidget extends Widget  
{  
    public function run()  
    {  
        $nav = 模型名::find()  
        ->where(['status' => 1])  
        ->orderBy('sort ASC')  
        ->all();  
        foreach($nav as $_v){  
            $navs[] = $_v->id.'|'.$_v->nav_cn.'|'.$_v->nav_en;  
        }  
        // 小部件需要渲染很多內容 所以就把內容放入一個檢視檔案         
        //當然也可以直接  return $nav;  
         return $this->render('@app/views/site/_nav', [  
             'nav'=>$navs,  
         ]);  
    }  
}  

小部件渲染的檢視在backend/views/site/_nav.php

如下:

use yii\helpers\Html;  
/* @var $this yii\web\View */  
use yii\bootstrap\Nav;  
use yii\bootstrap\NavBar;  
  
  
  
   NavBar::begin([  
        'brandLabel' => '首頁',  
        'brandUrl' => Yii::$app->homeUrl,  
        'options' => [  
            'class' => 'navbar-inverse navbar-fixed-top',  
            'id' => 'menu-top',  
        ],  
        //'brandOptions' => ['class' => 'fa fa-flag fa-2x pull-left'],  
  
    ]);  
  
    if (Yii::$app->user->isGuest) {  
        $menuItems[] = ['label' => '登陸', 'url' => ['/site/login']];  
    } else {  
      //迴圈一級導航    
      if(isset($nav)){  
            for($n=0;$n<count($nav);$n++){  
                $_v = explode('|',$nav[$n]);      
                $menuItems[] = [  
                    'label' => $_v[1],  
                    //這裡的url我建議寫當前這個導航預設的一個方法  
                   'url' => ["xxx",'id'=>$_v[0],'en'=>$_v[2]],  
                    'options' => ["id"=>"_M$n"],  
                ];  
  
            }  
        }  
        $menuItems[] = [  
            'label' => ' Log out',  
            'url' => ['/site/logout'],  
            'linkOptions' => ['data-method' => 'post','class'=>'fa fa-sign-out'],  
        ];  
  
    }  
    echo Nav::widget([  
        'options' => ['class' => 'navbar-nav navbar-right'],  
        'items' => $menuItems,  
  
    ]);  
    NavBar::end();  

現在,點選一級導航,二級導航怎麼會出來?

注:這裡難點是,怎麼把一個小部件裡面的id通過get方式傳到另一個小部件裡面去?

即通過得到一級導航的id迴圈出二三級導航

在NavWidget這個小部件渲染的內容裡有這麼一句

xxx....   
'url' => ["xxx",'id'=>$_v[0],'en'=>$_v[2]],  
xxx...  
這裡html裡面解析後就是這樣

xxx/index.php?r=set/default/index&id=1

所以,只要把id(一級導航ID)傳到第二個小部件(NavbarWidget)裡面去,如下

<?= NavbarWidget::widget(['id'=>$id]) ?>

這裡,這個小部件(NavbarWidget),就能獲得navWidget傳過來的di了,然後把二三級導航迴圈出來即可

namespace backend\components;  
use backend\models\二級導航模型;  
use backend\models\三級導航模型;  
use yii\base\Widget;  
use yii\helpers\Html;  
  
class NavbarWidget extends Widget  
{  
    public $id;  
    public $en;  
    public function run()  
    {  
        if(isset($this->id)){  
            $navbar = 三級導航模型::find()  
            ->with('navitem')   //這裡有一個關聯關係  
            ->where(['status' => 1,'nid'=>$this->id])  
            ->orderBy('id asc')  
            ->all();  
        }else{  
            $navbar = '';  
        }  
        return $this->render('@app/views/site/_navbar', [  
            "navbar"=>$navbar,  
            'naven' => $this->en,  
         ]);  
    }  
}