[widget] -- yii2小部件高階使用
原文連結 : http://blog.csdn.net/maclechan/article/details/46240183
(yii2.0高階應用)
注:以下佈局未使用iframe!
需求:在佈局中如何動態讀取選單欄資料?
最終效果如下:
說明:導航選單是寫進資料庫裡的,表nav 、navbar、navitem分別對應 一級/二級/三級選單欄 (當然你也可以只用一張表)如圖中的對應關係)。
導航資料是全域性都可訪問的,所以是不能寫進某個控制器裡面。因為又要使用佈局,一個比較好的解決方案就是使用小部件,這樣即可滿足佈局中可以動態讀取資料,還可以保證資料的全域性性。
一、佈局
如上圖,右側內容是可變的,所以除它外,所有內容都是放在backend/views/laouts下的
頂部的一級選單欄和左側的選單欄分別放入兩個小部件中,然後在佈局中註冊使用兩個小部件即可。
為什麼要用小部件? 因為要保證資料的全域性性。
佈局程式碼如下(部分)
佈局中使用小部件: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,
]);
}
}