首先我们介绍一下Controller类的render()方法的执行流程,需要查看vendor\yiisoft\yii2\base\Contorller.php文件中的render()方法源代码。

class Controller extends Component implements ViewContextInterface
{
 ......
  public function render($view, $params = [])
    {
        $content = $this->getView()->render($view, $params, $this);
        return $this->renderContent($content);
    }
 public function renderContent($content)
    {
        $layoutFile = $this->findLayoutFile($this->getView());
        if ($layoutFile !== false) {
            return $this->getView()->renderFile($layoutFile, ['content' => $content], $this);
        }

        return $content;
    }
}

分析render()方法源代码,画一个比较直观的流程图。

4.png

当render()方法被调用,首先调用View类的render()方法,该方法返回的内容赋值给变量$content,接下来把$content作为参数传递给renderController()方法。在renderController()方法中首先调用findLayoutFile()方法,渲染出布局文件,然后调用View类的renderFile()方法,完成局部文件和使徒的渲染。

开始应用级布局

在一个应用中多个控制器使用一个布局文件,那么可以在应用级配置文件config/web.php中设置yii/base/Application的$layout属性,代码如下:

$config = [
//layout config
    'layout' => 'headerfooter',
];

我们要做一个这样的布局页面,如下图所示:
5.png

首先,创建ArticleController.php文件,代码如下:

<?php
/**
 * Created by ZhengNiu.
 * User: admin
 * Date: 2019/10/12
 * Time: 17:49
 */

namespace app\controllers;

use yii\web\Controller;

class ArticleController extends Controller
{
    public $layout = 'right';

    public function actionIndex()
    {
        return $this->render('article');
    }

}

创建views/article.php,代码如下:

我是中间内容

创建views/layout/headerfooter.php,代码如下:

<h1>头部</h1>
<?= $content;?>
<h1>尾部</h1>

创建views/layout/right.php,代码如下:

<?php
$this->beginContent('@app/views/layouts/headerfooter.php');
?>
<?php
echo $content;
?>

我是left

<?php $this->endContent(); ?>

嵌套布局实现页面渲染流程:

  1. 首先渲染视图文件article.php的内容,存储到布局文件reght.php的$content中。
  2. 因为在布局文件right.php 中使用了另外一个布局文件headerfooter.php,所以又把article.php和right.php两个文件的内容存储到headerfooter.php文件的$content中。
  3. 最后渲染headerfooter.php布局文件,并且结果返回给用户。

视图文件的存储路径

修改配置文件config/web.php,代码如下:

return [
    ......
    'viewPath' => 'xxx',
];

配置文件config/web.php中的“viewPath”是yii\bash\Application类的属性.该类继承了yii\base\Module类,在Module类中定义了getViewPath()和setViewPath()方法,来获取和设置视图文件路径,代码如下所示:

//所在文件路径vendor\yiisoft\yii2\base\Application.php
abstract class Application extends Module
{

}
//所在文件路径vendor\yiisoft\yii2\base\Module.php
class Module extends ServiceLocator
{
  ......
    private $_viewPath;
    public function getViewPath()
    {
        if ($this->_viewPath === null) {
            $this->_viewPath = $this->getBasePath() . DIRECTORY_SEPARATOR . 'views';
        }

        return $this->_viewPath;
    }
    public function setViewPath($path)
    {
        $this->_viewPath = Yii::getAlias($path);
    }
}
  

在Module中并没有设施成员属性viewPath,但是使用viewPath成员属性时将自动调用_get()魔术方法间接调用getViewPath(),同理在设置viewPath成员属性时将自动调用_get()魔术方法间接调用setViewPath()方法。

渲染结果:

6.png

Last modification:October 17, 2019
如果觉得我的文章对你有用,请随意赞赏