我对yii2的控制器中的变量如何渲染到视图中这个问题一直很好奇,另外,我还对yii2如何加载静态资源,如js和css比较好奇,于是趁着周末就看了下yii2的相关源码想把这两个问题都弄明白。变量如何渲染到视图中是弄明白了,但是静态资源的加载问题还是没有弄明白,做人不难太贪心,先把这个弄明白了,后续再说另一个。

1,先把yii2中相关的关键代码贴出来看下

yii\web\View继承了yii\base\View

yii2的yii\base\View中的几个关键方法:

    public function render($view, $params = [], $context = null)
{
$viewFile = $this->findViewFile($view, $context);
return $this->renderFile($viewFile, $params, $context);
} public function renderFile($viewFile, $params = [], $context = null)
{
$viewFile = Yii::getAlias($viewFile);
if ($this->theme !== null) {
$viewFile = $this->theme->applyTo($viewFile);
}
if (is_file($viewFile)) {
$viewFile = FileHelper::localize($viewFile);
} else {
throw new ViewNotFoundException("The view file does not exist: $viewFile");
}
$oldContext = $this->context;
if ($context !== null) {
$this->context = $context;
}
$output = '';
$this->_viewFiles[] = $viewFile;
if ($this->beforeRender($viewFile, $params)) {
Yii::trace("Rendering view file: $viewFile", __METHOD__);
$ext = pathinfo($viewFile, PATHINFO_EXTENSION);
if (isset($this->renderers[$ext])) {
if (is_array($this->renderers[$ext]) || is_string($this->renderers[$ext])) {
$this->renderers[$ext] = Yii::createObject($this->renderers[$ext]);
}
/* @var $renderer ViewRenderer */
$renderer = $this->renderers[$ext];
$output = $renderer->render($this, $viewFile, $params);
} else {
$output = $this->renderPhpFile($viewFile, $params);
}
$this->afterRender($viewFile, $params, $output);
}
array_pop($this->_viewFiles);
$this->context = $oldContext;
return $output;
} public function renderPhpFile($_file_, $_params_ = [])
{
ob_start();
ob_implicit_flush(false);
extract($_params_, EXTR_OVERWRITE);
require($_file_);
return ob_get_clean();
}

我现在这个水平只是对代码(功能)的实现比较好奇,其实yii2框架代码的组织、框架设计都很值得学习,不过这都是后话,先把好奇的东西研究下。

功能实现的关键就在renderPhpFile($_file_, $_params_ = [])这个方法里,而这个方法的关键又是:extract($_params, EXTR_OVERWRITE);,这个php函数的神奇之处在于,它可以将关联数组导入到一个变量表中,就是将数组键作为变量名、值作为变量的值进行赋值。比如下面这个简单的例子:

Psy Shell v0.7.2 (PHP 5.6.29 — cli) by Justin Hileman 
1 >>> $arr = ['a' => 2, 'b' => 3];
=> [
"a" => 2,
"b" => 3,
]
>>> extract($arr);
=> 2
>>> $a
=> 2
>>> $b
=> 3

那么yii2视图中的变量值是怎么传递过来的也就很好理解了。

2,变量注入过程的简单分析

ob_start()打开输出缓冲区,这样php脚本中要输出的内容,比如变量值等,就不会输出到输出设备(如屏幕),而是存储到php自身的一个缓冲区中,在这些内容被冲刷出缓冲区之前,我们可以对这些内容进行操作,比如格式化下等。

ob_implicit_flush(false)关闭内部的绝对(隐式)刷送,它的效果其实等同于调用flush()只不过如果打开它那就不用再主动调用flush()了,打开它将会在每次输出调用之后都会有一次刷送,那么在将变量注入到视图文件中时就需要关闭它,否则在视图还没渲染(可以理解为页面加载完成)完成时,这些变量就会输出到屏幕。

extract($_params, EXTR_OVERWRITE);将控制器变量数组键值注入到对应的键名变量列表。

require($_file);加载视图文件

return ob_get_clean(); ob_get_clean()获取当前缓冲区内容,关闭(删除)当前的输出缓冲区。

3,视图渲染过程的简单分析

这个。。。时间有点儿晚了,有时间再说。

参考资料:

php手册

yii2


完

yii2的变量是如何注入到视图中去的?的更多相关文章

  1. ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入

    原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...

  2. 基础教程:视图中的ASP.NET Core 2.0 MVC依赖注入

    问题 如何在ASP.NET Core MVC Views中注入和使用服务. 解 更新 启动 类来为MVC添加服务和中间件. 添加一项服务 添加一个Controller,返回 ViewResult. 添 ...

  3. YbSoftwareFactory 代码生成插件【二十五】:Razor视图中以全局方式调用后台方法输出页面代码的三种方法

    上一篇介绍了 MVC中实现动态自定义路由 的实现,本篇将介绍Razor视图中以全局方式调用后台方法输出页面代码的三种方法. 框架最新的升级实现了一个页面部件功能,其实就是通过后台方法查询数据库内容,把 ...

  4. django在视图中使用模板

    在视图中使用模板   在学习了模板系统的基础之后,现在让我们使用相关知识来创建视图. 重新打开我们在前一章在 mysite.views 中创建的 current_datetime 视图. 以下是其内容 ...

  5. MFC中 在SDI模式下的视图中添加按钮的方法

    在单文档视图(SDI)结构中,视图一般用来显示数据.但是,有时也希望在视图中显示按钮或其他的控件,以满足用户的需要.下面是手动添加按钮并使按钮具有响应事件的功能的方法. 第一步:添加一个按钮      ...

  6. Unity3D研究院之Inspector视图中的get/set使用

    get set 使用起来很方便,但是编辑时在Inspector视图中问题就来了,因为get/set的属性即使是public了,但是在Inspector视图中依然不显示..谷歌一下估计就是下面这样的答案 ...

  7. 如何在“代码”视图中工作并充分利用 Dreamweaver 的编码功能。如 Emmet 缩写

    可通过多种方式在 Dreamweaver 中处理代码. 您可以使用“新建文档”对话框打开新的代码文件,然后开始键入您的代码. 在 Dreamweaver 中创建新的代码文件 键入时,会显示代码提示以帮 ...

  8. Razor视图中的@:和语法

    Razor视图中的@:和语法 原创changuncle 最后发布于2016-12-07 17:43:50 阅读数 4456  收藏 展开 在MVC项目中新建视图的时候默认支持ASPX引擎和Razor引 ...

  9. Servlet规范简介——web框架是如何注入到Servlet中的

    Servlet规范简介--web框架是如何注入到Servlet中的 引言 Web框架一般是通过一个Servlet提供统一的请求入口,将指定的资源映射到这个servlet,在这个servlet中进行框架 ...

随机推荐

  1. 函数返回值 return

    return 返回值 (后面跟的是数据类型) // 数字.字符串.布尔.函数.对象(元素.[].{}.null).未定义return:返回值 1)函数名+括号:fn1() ==> return ...

  2. jq操作radio,设置选中、获取选中值

    <label><inputtype="radio"name="sex"value="1">男</label&g ...

  3. linux下安装TensorFlow(centos)

    一.python安装 centos自带python2.7.5,这一步可以省略掉. 二.python-pip pip--python index package,累世linux的yum,安装管理pyth ...

  4. redis的配置详解

    redis 127.0.0.1:6379> CONFIG GET loglevel 1) "loglevel" 2) "notice" Redis 的配置 ...

  5. Android内存泄露---检测工具篇

    内存使用是程序开发无法回避的一个问题.如果我们毫不在意肆意使用,总有一天会为此还账,且痛不欲生...所以应当防患于未然,把内存使用细化到平时的每一行代码中. 内存使用概念较大,本篇先讲对已有app如何 ...

  6. SDWebImage源码解读之SDWebImagePrefetcher

    > 第十篇 ## 前言 我们先看看`SDWebImage`主文件的组成模块: ![](http://images2015.cnblogs.com/blog/637318/201701/63731 ...

  7. Jquery实现的几款漂亮的时间轴

    引言 最近项目中使用了很多前端的东西,对于我一个做后台开发的人员,这是一个很好的锻炼的机会.经过这段时间的学习,感觉前端的东西太多了,太强大了,做出来的东西太炫酷了.现在有很多开源的前端框架,做的都非 ...

  8. Javascript中的async await

    async / await是Javascript是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案.目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度 ...

  9. KB奇遇记(3):IT现状

    2015年8月3号,终于告别了过去来到了KB. 公司给安排的住房是一间套房里的小房间,小的简直连坐的地方都没有了,中间一个大床将房间隔了两边,显得特别狭小.由于是刚来,我也不好要求太多.但就这个小房间 ...

  10. IOS解析XML

    XML也许是我们储存数据和通讯数据中最常见的一种简易方式,当我们来到XML的海洋时,我们会发现当我们用iPhone程序解析XML时,我们是有如此多的选项,让人眼花缭乱.iOS SDK本身就带有两种不同 ...