您的位置:首页 > 编程语言 > PHP开发

Yii2.0实用功能技巧解密之——布局文件多变量继承(嵌套、引用)终极功能

2014-06-22 13:43 471 查看
在做网站的过程中,大部分的页面结构都是相似的。如都有相同的头部和底部。各个页面这样仅仅是中间的部分不同。
Yii中的布局文件就是用来实现这样的功能。如:

布局文件:@app/views/layouts/main.php

<!-- 前后的html 、head、body代码就省略了,只看最主要的部分 -->
<header>
</header>
<div class="wrap">
<div class="container">
<!-- $content变量的值 就是子页面渲染之后的代码。也就是说子页面中的内容将输出到这个地方-->
<?= $content ?>
</div>
</div>
<footer class="footer">
</footer>


后台action:

public function actionIndex()
{
$this->layout='@app/views/layouts/main.php';
return $this->render('index');
}


执行顺序为:

先想找index视图文件,

渲染index视图文件 作为变量$output

查找布局文件@app/views/layouts/main.php

如果找到,则把$output值作为变量$content传递到布局文件

把渲染后的布局文件作为结果返回

如果没有找到布局文件,直接把$output作为结果返回

上面这个布局就是一列布局的页面,现在我们再增加另外一个布局:页面显示2列,左侧显示主要的内容,右侧显示统计信息。这个时候怎么办,再写一个和上面基本完全一样的代码吗?

布局文件嵌套(小部件:ContentDecorator)
这个小部件就是专为此功能而生的。
它的功能就是把begin和end之间的内容作为变量$content的值,然后渲染指定的视图文件。

两列布局文件:@app/views/layouts/column_2.php

<!-- 先引用main.php布局文件, -->
<?php $this->beginContent('@app/views/layouts/main.php');?>
<div class="left_column">
<?= $content ?>
</div>

<div class="right_column">
<!-- 在右侧共用的统一数据 -->
</div>
<?php $this->endContent();?>


把上面的action改为:

public function actionIndex()
{
$this->layout='@app/views/layouts/column_2.php';
return $this->render('index');
}


执行顺序为:

先把视图index渲染之后的结果作为变量$content传递到布局文件column_2中

再把布局文件column_2中的beginContent和endContent之间的内容作为变量$content传递到布局文件@app/views/layouts/main.php中

最后把main.php文件的结果输出。

注意:在上面布局文件column_2中,在beginContent和endContent之外的内容是不会显示。

因此Yii中布局文件可以通过ContentDecorator小部件进行无限的嵌套。当然要小心点,不要弄成死循环了,如:ayout1引用layout2,layout2引用layout1文件

到现在你以为本文就结束了吗?终极技巧解密才刚刚开始!!!!!

多变量继承

先给你们看一个实例:

布局文件maiin:app/views/layouts/main.php

<header>
</header>
<div class="wrap">
<div class="container">
<?= $content ?>
</div>
</div>
<footer class="footer">
<div>
<?= $footer ?>
</div>
</footer>


可以看到,里面有两个变量:$content和$footer。

布局文件columns_2:@app/views/layouts/columns_2.php

<?php AreaDecorator::begin(['viewFile'=>'@app/views/layouts/main.php'])?>

<?php Block::begin(['id' =>'content']);?>
<div class="main_column">
<?= $mainData ?>
</div>
<div class="side_column">
<?= $sideData ?>
</div>
<?php Block::end();?>

<?php Block::begin(['id' =>'footer']);?>
<div>footer data </div>
<?php Block::end();?>

<?php AreaDecorator::end();?>


布局文件columns_2引用main,并通过Block的id指定main里面的两个变量的内容

布局文件columns_3:@app/views/layouts/columns_3.php

<?php AreaDecorator::begin(['viewFile'=>'@app/views/layouts/columns_2.php'])?>

<?php  Block::begin(['id' =>'mainData']);?>
<div class="main_column_left">
<div>main column left data</div>
</div>
<div class="main_column_right">
<div><?= $content ?></div>
</div>
<?php Block::end();?>

<?php Block::begin(['id' =>'sideData']);?>
<div class="side_column">
side data
</div>
<?php Block::end();?>

<?php AreaDecorator::end();?>


这个和上面的类似

action使用:

public function actionIndex()
{
$this->layout='@app/views/layouts/columns_3.php';
return $this->render('index');
}


在布局中可以定义多个点位符变量,然后在各个子布局中指定所使用的内容。

现在再也不用担心Yii布局里面只提供一个$content变量了

下面就是实现这个功能的小部件类
AreaDecorator小部件类:

class AreaDecorator extends Widget
{
public $viewFile;

public $params = [];

public $ids=[];

public function init()
{
if ($this->viewFile === null) {
throw new InvalidConfigException('ContentDecorator::viewFile must be set.');
}
ob_start();
ob_implicit_flush(false);
}

public function run()
{
$params = $this->params;
$params['content'] = ob_get_clean();

$blocks = $this->view->blocks;
if(count($this->ids)>0)
{
foreach ($blocks as $id=>$block)
{
if(in_array($id,$this->ids))
{
$params[$id]=$block;
unset($this->view->blocks[$id]);
}
}
}
else
{
foreach ($blocks as $id=>$block)
{
$params[$id]=$block;
unset($this->view->blocks[$id]);
}
}

echo $this->view->renderFile($this->viewFile, $params);
}
}


原文链接:http://www.yiifans.com/forum.php?mod=viewthread&tid=76
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: