(注:此为yii2高级应用)
需求:在布局中如何动态读取数据表中数据?并且具有全局性(即数据在全站都可有效)?
如上:除了使用session外,还有一种比较好的方式就是使用小部件。
带着问题进入事例:
在创建一个项目的后台,我把菜单导航栏写进数据表,所有菜单导航栏是通过数据表来控制的。那么,在布局中如何把菜单读出来呢?如下图
如果使用控制器来渲染,菜单栏是不具有全局性。
这时,不部件是一个好的方案!不仅解决了读取数据表中的数据,还保证了菜单栏的全局性。
一、创建数据表 nav(菜单),并使用gii创建model
此表用来保存所有菜单数据。此步很简单,在此略过!
每个人的方式不一样,此例主要是讲解如何使用小物件。
二、创建小部件
在backend下创建components/NavWidget.php (高级应用后台是没有components的)
<?php
namespace backend\components;
use backend\models\Nav;
use yii\base\Widget;
use yii\helpers\Html;
class NavWidget extends Widget
{
public function run()
{
//从数据表中读出数据
$nav = Nav::find()
->where(['status' => 1])
->orderBy('sort ASC')
->all();
foreach($nav as $_v){
$navs[] = $_v->id.'|'.$_v->nav_cn.'|'.$_v->nav_en;
}
// 渲染视图
return $this->render('@app/views/site/_nav', [
'nav'=>$navs,
]);
}
}
?>
run()方法是处理和返回数据表中的数据;
这里是return了一个_nav.php的视图文件(具体地址是在backend/views/site/_nav.php),
因为小部件需要渲染很多复杂内容,一种更好的办法是将内容放入这个视图文件里面。
如果内容很少就直接return $nav;如果render不指定一个具体的地址会默认在backend/components/views/xxx.php;
让我们看一眼这个小部件渲染的视图文件 如下:
use yii\helpers\Html;
/* @var $this yii\web\View */
use yii\bootstrap\Nav;
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' => ["/$_v[2]/default/index",'id'=>$_v[0],'en'=>$_v[2]],
//'linkOptions' => ['class' => 'active'],
//'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();
三、创建布局文件并使用刚创建的小部件
backend/views/layouts/main.php
//使用小部件
<?= NavWidget::widget() ?>
这样,小部件里面的动态数据就出来了,并且全局可使用。
另外:你如果想把NavWidget小部件里面有些参数通过get传到NewWidget这个小部件里面去(反正我是有这个需求的),可通过下面这种方式
在NavWidget渲染的视图里面(这段在上面有) 传个ID给别的小部件里面使用
'url' => ["/$_v[2]/default/index",'id'=>$_v[0]],
别的小部件使用处接收下
$id = isset($_GET['id']) ? $_GET['id'] : 1;
NewWidget::widget(['id'=>$id])
在NewWidget小部件里(部分代码)接收id
namespace backend\components;
use yii\base\Widget;
use yii\helpers\Html;
class NewWidget extends Widget
{
public $id; //调用处把这个id传进来了
public function run()
{
if(isset($this->id)){
$navbar = xxx::find()
->with('xxx') //联表
->where(['status' => 1,'nid'=>$this->id])//id就这样被使用了
->orderBy('id asc')
->all();
}else{
$navbar = '';
}
//......
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。