Heim  >  Artikel  >  php教程  >  yii2源码学习笔记(十八),

yii2源码学习笔记(十八),

WBOY
WBOYOriginal
2016-07-06 14:24:56790Durchsuche

yii2源码学习笔记(十八),

View继承了component,用于渲染视图文件:yii2\base\View.php

<span>  1</span> <?<span>php
</span><span>  2</span> <span>/*</span><span>*
</span><span>  3</span> <span> * @link </span><span>http://www.yiiframework.com/</span>
<span>  4</span> <span> * @copyright Copyright (c) 2008 Yii Software LLC
</span><span>  5</span> <span> * @license </span><span>http://www.yiiframework.com/license/</span>
<span>  6</span>  <span>*/</span>
<span>  7</span> 
<span>  8</span> <span>namespace</span> yii\<span>base</span><span>;
</span><span>  9</span> 
<span> 10</span> <span>use Yii;
</span><span> 11</span> <span>use yii\helpers\FileHelper;
</span><span> 12</span> <span>use yii\widgets\Block;
</span><span> 13</span> <span>use yii\widgets\ContentDecorator;
</span><span> 14</span> <span>use yii\widgets\FragmentCache;
</span><span> 15</span> 
<span> 16</span> <span>/*</span><span>*
</span><span> 17</span> <span> * View represents a view object in the MVC pattern.
</span><span> 18</span> <span> * MVC中的视图
</span><span> 19</span> <span> * View provides a set of methods (e.g. [[render()]]) for rendering purpose.
</span><span> 20</span> <span> * 视图提供了一套渲染页面的方法
</span><span> 21</span> <span> * @property string|boolean $viewFile The view file currently being rendered. False if no view file is being
</span><span> 22</span> <span> * rendered. This property is read-only.
</span><span> 23</span> <span> *
</span><span> 24</span> <span> * @author Qiang Xue <qiang.xue@gmail.com>
</span><span> 25</span> <span> * @since 2.0
</span><span> 26</span>  <span>*/</span>
<span> 27</span> <span>class</span><span> View extends Component
</span><span> 28</span> <span>{
</span><span> 29</span>     <span>/*</span><span>*
</span><span> 30</span> <span>     * @event Event an event that is triggered by [[beginPage()]].
</span><span> 31</span> <span>     * 事件被[beginPage()]触发
</span><span> 32</span>      <span>*/</span>
<span> 33</span>     <span>const</span> EVENT_BEGIN_PAGE = <span>'</span><span>beginPage</span><span>'</span><span>;
</span><span> 34</span>     <span>/*</span><span>*
</span><span> 35</span> <span>     * @event Event an event that is triggered by [[endPage()]].
</span><span> 36</span> <span>     * 事件被[endPage()]触发
</span><span> 37</span>      <span>*/</span>
<span> 38</span>     <span>const</span> EVENT_END_PAGE = <span>'</span><span>endPage</span><span>'</span><span>;
</span><span> 39</span>     <span>/*</span><span>*
</span><span> 40</span> <span>     * @event ViewEvent an event that is triggered by [[renderFile()]] right before it renders a view file.
</span><span> 41</span> <span>     * 事件被[renderFile()]触发前呈现一个视图文件
</span><span> 42</span>      <span>*/</span>
<span> 43</span>     <span>const</span> EVENT_BEFORE_RENDER = <span>'</span><span>beforeRender</span><span>'</span><span>;
</span><span> 44</span>     <span>/*</span><span>*
</span><span> 45</span> <span>     * @event ViewEvent an event that is triggered by [[renderFile()]] right after it renders a view file.
</span><span> 46</span> <span>     * 事件被[renderFile()]触发后呈现一个视图文件
</span><span> 47</span>      <span>*/</span>
<span> 48</span>     <span>const</span> EVENT_AFTER_RENDER = <span>'</span><span>afterRender</span><span>'</span><span>;
</span><span> 49</span> 
<span> 50</span>     <span>/*</span><span>*
</span><span> 51</span> <span>     * @var ViewContextInterface the context under which the [[renderFile()]] method is being invoked.
</span><span> 52</span> <span>     * ViewContextInterface背景下 [renderFile()]方法被调用
</span><span> 53</span>      <span>*/</span>
<span> 54</span>     <span>public</span><span> $context;
</span><span> 55</span>     <span>/*</span><span>*
</span><span> 56</span> <span>     * @var mixed custom parameters that are shared among view templates.
</span><span> 57</span> <span>     * 视图模板中共享的自定义参数
</span><span> 58</span>      <span>*/</span>
<span> 59</span>     <span>public</span> $<span>params</span> =<span> [];
</span><span> 60</span>     <span>/*</span><span>*
</span><span> 61</span> <span>     * @var array a list of available renderers indexed by their corresponding supported file extensions.
</span><span> 62</span> <span>     * Each renderer may be a view renderer object or the configuration for creating the renderer object.
</span><span> 63</span> <span>     *  一个可用的渲染索引列表。每个渲染器是一个渲染器对象或创建渲染对象配置数组
</span><span> 64</span> <span>     * For example, the following configuration enables both Smarty and Twig view renderers:
</span><span> 65</span> <span>     *
</span><span> 66</span> <span>     * ~~~
</span><span> 67</span> <span>     * [
</span><span> 68</span> <span>     *     'tpl' => ['class' => 'yii\smarty\ViewRenderer'],
</span><span> 69</span> <span>     *     'twig' => ['class' => 'yii\twig\ViewRenderer'],
</span><span> 70</span> <span>     * ]
</span><span> 71</span> <span>     * ~~~
</span><span> 72</span> <span>     *
</span><span> 73</span> <span>     * If no renderer is available for the given view file, the view file will be treated as a normal PHP
</span><span> 74</span> <span>     * and rendered via [[renderPhpFile()]].
</span><span> 75</span>      <span>*/</span>
<span> 76</span>     <span>public</span><span> $renderers;
</span><span> 77</span>     <span>/*</span><span>*
</span><span> 78</span> <span>     * @var string the default view file extension. This will be appended to view file names if they don't have file extensions.
</span><span> 79</span> <span>     * 默认视图文件扩展名,文件没有扩展名的情况下自动加载
</span><span> 80</span>      <span>*/</span>
<span> 81</span>     <span>public</span> $defaultExtension = <span>'</span><span>php</span><span>'</span><span>;
</span><span> 82</span>     <span>/*</span><span>*
</span><span> 83</span> <span>     * @var Theme|array|string the theme object or the configuration for creating the theme object.
</span><span> 84</span> <span>     * If not set, it means theming is not enabled.主题对象或创建主题对象的配置 未设置则不启用
</span><span> 85</span>      <span>*/</span>
<span> 86</span>     <span>public</span><span> $theme;
</span><span> 87</span>     <span>/*</span><span>*
</span><span> 88</span> <span>     * @var array a list of named output blocks. The keys are the block names and the values
</span><span> 89</span> <span>     * are the corresponding block content. You can call [[beginBlock()]] and [[endBlock()]]
</span><span> 90</span> <span>     * to capture small fragments of a view. They can be later accessed somewhere else
</span><span> 91</span> <span>     * through this property.
</span><span> 92</span> <span>     * 一个输出块列表。键是块名称值为内容。可以调用 [beginblock()]和[endblock()]捕获视图的小片段
</span><span> 93</span> <span>     * 可以在其他地方通过这个属性访问。
</span><span> 94</span>      <span>*/</span>
<span> 95</span>     <span>public</span><span> $blocks;
</span><span> 96</span>     <span>/*</span><span>*
</span><span> 97</span> <span>     * @var array a list of currently active fragment cache widgets. This property
</span><span> 98</span> <span>     * is used internally to implement the content caching feature. Do not modify it directly.
</span><span> 99</span> <span>     * 当前操作片段的缓存部件列表。用于内部实现内容缓存功能。不要直接修改
</span><span>100</span> <span>     * @internal
</span><span>101</span>      <span>*/</span>
<span>102</span>     <span>public</span> $cacheStack =<span> [];
</span><span>103</span>     <span>/*</span><span>*
</span><span>104</span> <span>     * @var array a list of placeholders for embedding dynamic contents. This property
</span><span>105</span> <span>     * is used internally to implement the content caching feature. Do not modify it directly.
</span><span>106</span> <span>     * 嵌入动态内容占位符列表。 用于内部实现内容缓存功能。不要直接修改
</span><span>107</span> <span>     * @internal
</span><span>108</span>      <span>*/</span>
<span>109</span>     <span>public</span> $dynamicPlaceholders =<span> [];
</span><span>110</span> 
<span>111</span>     <span>/*</span><span>*
</span><span>112</span> <span>     * @var array the view files currently being rendered. There may be multiple view files being
</span><span>113</span> <span>     * rendered at a moment because one view may be rendered within another.
</span><span>114</span> <span>     * 正在渲染的视图文件。可能有多个视图文件被渲染,因为一个视图可以在另一个视图中呈现
</span><span>115</span>      <span>*/</span>
<span>116</span>     <span>private</span> $_viewFiles =<span> [];
</span><span>117</span> 
<span>118</span> 
<span>119</span>     <span>/*</span><span>*
</span><span>120</span> <span>     * Initializes the view component.初始化视图组件
</span><span>121</span>      <span>*/</span>
<span>122</span>     <span>public</span><span> function init()
</span><span>123</span> <span>    {
</span><span>124</span>         parent::init(); <span>//</span><span>调用父类的方法</span>
<span>125</span>         <span>if</span> (is_array($<span>this</span>-><span>theme)) {
</span><span>126</span>             <span>if</span> (!isset($<span>this</span>->theme[<span>'</span><span>class</span><span>'</span><span>])) {
</span><span>127</span>                 $<span>this</span>->theme[<span>'</span><span>class</span><span>'</span>] = <span>'</span><span>yii\base\Theme</span><span>'</span>;<span>//</span><span>是数组,没有设置类名,则类名'yii\base\Theme'</span>
<span>128</span> <span>            }
</span><span>129</span>             $<span>this</span>->theme = Yii::createObject($<span>this</span>->theme);<span>//</span><span>设置了类名,调用配置创建对象</span>
<span>130</span>         } elseif (is_string($<span>this</span>->theme)) {<span>//</span><span>以字符串参数的形式创建对象</span>
<span>131</span>             $<span>this</span>->theme = Yii::createObject($<span>this</span>-><span>theme);
</span><span>132</span> <span>        }
</span><span>133</span> <span>    }
</span><span>134</span> 
<span>135</span>     <span>/*</span><span>*
</span><span>136</span> <span>     * Renders a view.
</span><span>137</span> <span>     * 渲染一个视图
</span><span>138</span> <span>     * The view to be rendered can be specified in one of the following formats:
</span><span>139</span> <span>     *
</span><span>140</span> <span>     * - path alias (e.g. "@app/views/site/index");
</span><span>141</span> <span>     * 路径别名
</span><span>142</span> <span>     * - absolute path within application (e.g. "//site/index"): the view name starts with double slashes.
</span><span>143</span> <span>     *   The actual view file will be looked for under the [[Application::viewPath|view path]] of the application.
</span><span>144</span> <span>     *  绝对路径,会在[Application::viewPath|view path]下查找文件
</span><span>145</span> <span>     * - absolute path within current module (e.g. "/site/index"): the view name starts with a single slash.
</span><span>146</span> <span>     *   The actual view file will be looked for under the [[Module::viewPath|view path]] of the [[Controller::module|current module]].
</span><span>147</span> <span>     * 模块下的绝对路径,会在[Module::viewPath|view path]下查找文件
</span><span>148</span> <span>     * - relative view (e.g. "index"): the view name does not start with `@` or `/`. The corresponding view file will be
</span><span>149</span> <span>     *   looked for under the [[ViewContextInterface::getViewPath()|view path]] of the view `$context`.
</span><span>150</span> <span>     * 相对路径,会在[ViewContextInterface::getViewPath()|view path]下查找文件  
</span><span>151</span> <span>     * If `$context` is not given, it will be looked for under the directory containing the view currently
</span><span>152</span> <span>     *   being rendered (i.e., this happens when rendering a view within another view).
</span><span>153</span> <span>     *
</span><span>154</span> <span>     * @param string $view the view name.   视图名称
</span><span>155</span> <span>     * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
</span><span>156</span> <span>     * 视图中应用参数
</span><span>157</span> <span>     * @param object $context the context to be assigned to the view and can later be accessed via [[context]]
</span><span>158</span> <span>     * in the view. If the context implements [[ViewContextInterface]], it may also be used to locate
</span><span>159</span> <span>     * the view file corresponding to a relative view name. 对应情景
</span><span>160</span> <span>     * @return string the rendering result
</span><span>161</span> <span>     * @throws InvalidParamException if the view cannot be resolved or the view file does not exist.
</span><span>162</span> <span>     * @see renderFile()
</span><span>163</span>      <span>*/</span>
<span>164</span>     <span>public</span> function render($view, $<span>params</span> = [], $context = <span>null</span><span>)
</span><span>165</span> <span>    {
</span><span>166</span>         $viewFile = $<span>this</span>->findViewFile($view, $context);<span>//</span><span>查找视图文件路径</span>
<span>167</span>         <span>return</span> $<span>this</span>->renderFile($viewFile, $<span>params</span>, $context);<span>//</span><span>渲染视图文件</span>
<span>168</span> <span>    }
</span><span>169</span> 
<span>170</span>     <span>/*</span><span>*
</span><span>171</span> <span>     * Finds the view file based on the given view name.通过视图文件名查找视图文件
</span><span>172</span> <span>     * @param string $view the view name or the path alias of the view file. Please refer to [[render()]]
</span><span>173</span> <span>     * on how to specify this parameter. 视图名称或路径视图文件的别名
</span><span>174</span> <span>     * @param object $context the context to be assigned to the view and can later be accessed via [[context]]
</span><span>175</span> <span>     * in the view. If the context implements [[ViewContextInterface]], it may also be used to locate
</span><span>176</span> <span>     * the view file corresponding to a relative view name. 对应情景
</span><span>177</span> <span>     * @return string the view file path. Note that the file may not exist. 文件路径
</span><span>178</span> <span>     * @throws InvalidCallException if a relative view name is given while there is no active context to
</span><span>179</span> <span>     * determine the corresponding view file.
</span><span>180</span>      <span>*/</span>
<span>181</span>     <span>protected</span> function findViewFile($view, $context = <span>null</span><span>)
</span><span>182</span> <span>    {
</span><span>183</span>         <span>if</span> (strncmp($view, <span>'</span><span>@</span><span>'</span>, <span>1</span>) === <span>0</span><span>) {
</span><span>184</span>             <span>//</span><span> e.g. "@app/views/main"  判断是否是别名路径,是则获取真实路径</span>
<span>185</span>             $file =<span> Yii::getAlias($view);
</span><span>186</span>         } elseif (strncmp($view, <span>'</span><span>//</span><span>'</span>, <span>2</span>) === <span>0</span><span>) {
</span><span>187</span>             <span>//</span><span> e.g. "</span><span>//</span><span>layouts/main" 以</span><span>//</span><span>开始,查找文件路径,拼接视图文件路径</span>
<span>188</span>             $file = Yii::$app->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, <span>'</span><span>/</span><span>'</span><span>);
</span><span>189</span>         } elseif (strncmp($view, <span>'</span><span>/</span><span>'</span>, <span>1</span>) === <span>0</span><span>) {
</span><span>190</span>             <span>//</span><span> e.g. "/site/index"</span>
<span>191</span>             <span>if</span> (Yii::$app->controller !== <span>null</span><span>) { 
</span><span>192</span>                 <span>//</span><span>以/开始,且控制器存在,查找控制器对应的文件目录,拼接路径</span>
<span>193</span>                 $file = Yii::$app->controller->module->getViewPath() . DIRECTORY_SEPARATOR . ltrim($view, <span>'</span><span>/</span><span>'</span><span>);
</span><span>194</span>             } <span>else</span><span> {
</span><span>195</span>                 <span>throw</span> <span>new</span> InvalidCallException(<span>"</span><span>Unable to locate view file for view '$view': no active controller.</span><span>"</span><span>);
</span><span>196</span> <span>            }
</span><span>197</span> <span>        } elseif ($context instanceof ViewContextInterface) {
</span><span>198</span>             <span>//</span><span>对应情景存在 查找文件路径,拼接视图文件路径</span>
<span>199</span>             $file = $context-><span>getViewPath() . DIRECTORY_SEPARATOR . $view;
</span><span>200</span>         } elseif (($currentViewFile = $<span>this</span>->getViewFile()) !== <span>false</span><span>) {
</span><span>201</span>             <span>//</span><span>当前渲染文件存在,拼接路径</span>
<span>202</span>             $file =<span> dirname($currentViewFile) . DIRECTORY_SEPARATOR . $view;
</span><span>203</span>         } <span>else</span><span> {
</span><span>204</span>             <span>throw</span> <span>new</span> InvalidCallException(<span>"</span><span>Unable to resolve view file for view '$view': no active view context.</span><span>"</span><span>);
</span><span>205</span> <span>        }
</span><span>206</span> 
<span>207</span>         <span>if</span> (pathinfo($file, PATHINFO_EXTENSION) !== <span>''</span><span>) {
</span><span>208</span>             <span>return</span> $file;<span>//</span><span>视图文件的扩展名不为空,返回扩展名</span>
<span>209</span> <span>        }
</span><span>210</span>         $path = $file . <span>'</span><span>.</span><span>'</span> . $<span>this</span>->defaultExtension; <span>//</span><span>给视图文件添加扩展名</span>
<span>211</span>         <span>if</span> ($<span>this</span>->defaultExtension !== <span>'</span><span>php</span><span>'</span> && !<span>is_file($path)) {
</span><span>212</span>             $path = $file . <span>'</span><span>.php</span><span>'</span><span>;
</span><span>213</span> <span>        }
</span><span>214</span> 
<span>215</span>         <span>return</span> $path;<span>//</span><span>返回路径</span>
<span>216</span> <span>    }
</span><span>217</span> 
<span>218</span>     <span>/*</span><span>*
</span><span>219</span> <span>     * Renders a view file.
</span><span>220</span> <span>     * 渲染一个视图文件。
</span><span>221</span> <span>     * If [[theme]] is enabled (not null), it will try to render the themed version of the view file as long
</span><span>222</span> <span>     * as it is available.
</span><span>223</span> <span>     * 如果[theme]可用,将渲染视图文件的主题版本直到[theme]不可用
</span><span>224</span> <span>     * The method will call [[FileHelper::localize()]] to localize the view file.
</span><span>225</span> <span>     * 调用[FileHelper::localize()]方法本地化视图文件
</span><span>226</span> <span>     * If [[renderers|renderer]] is enabled (not null), the method will use it to render the view file.
</span><span>227</span> <span>     * Otherwise, it will simply include the view file as a normal PHP file, capture its output and
</span><span>228</span> <span>     * return it as a string.
</span><span>229</span> <span>     * 如果[[renderers|renderer]]启用,该方法将用它来渲染视图文件。否则,将视图文件作为一个正常的PHP文件包含进来,获取其输出并返回一个字符串。
</span><span>230</span> <span>     * @param string $viewFile the view file. This can be either an absolute file path or an alias of it.
</span><span>231</span> <span>     * 视图文件。可以是绝对路径或它的别名。
</span><span>232</span> <span>     * @param array $params the parameters (name-value pairs) that will be extracted and made available in the view file.
</span><span>233</span> <span>     * 视图文件执行的参数
</span><span>234</span> <span>     * @param object $context the context that the view should use for rendering the view. If null,
</span><span>235</span> <span>     * existing [[context]] will be used.
</span><span>236</span> <span>     * 用于渲染视图的上下文
</span><span>237</span> <span>     * @return string the rendering result 
</span><span>238</span> <span>     * @throws InvalidParamException if the view file does not exist
</span><span>239</span>      <span>*/</span>
<span>240</span>     <span>public</span> function renderFile($viewFile, $<span>params</span> = [], $context = <span>null</span><span>)
</span><span>241</span> <span>    {
</span><span>242</span>         $viewFile = Yii::getAlias($viewFile);<span>//</span><span>处理输入的视图文件名</span>
<span>243</span> 
<span>244</span>         <span>if</span> ($<span>this</span>->theme !== <span>null</span><span>) {
</span><span>245</span>             $viewFile = $<span>this</span>->theme->applyTo($viewFile);<span>//</span><span>如果theme非空,应用到视图文件</span>
<span>246</span> <span>        }
</span><span>247</span>         <span>if</span><span> (is_file($viewFile)) {
</span><span>248</span>             $viewFile = FileHelper::localize($viewFile);<span>//</span><span>本地化视图文件</span>
<span>249</span>         } <span>else</span><span> {
</span><span>250</span>             <span>throw</span> <span>new</span> InvalidParamException(<span>"</span><span>The view file does not exist: $viewFile</span><span>"</span><span>);
</span><span>251</span> <span>        }
</span><span>252</span> 
<span>253</span>         $oldContext = $<span>this</span>-><span>context;
</span><span>254</span>         <span>if</span> ($context !== <span>null</span><span>) {
</span><span>255</span>             $<span>this</span>->context =<span> $context;
</span><span>256</span> <span>        }
</span><span>257</span>         $output = <span>''</span><span>;
</span><span>258</span>         $<span>this</span>->_viewFiles[] = $viewFile;<span>//</span><span>记录当前渲染文件</span>
<span>259</span> 
<span>260</span>         <span>if</span> ($<span>this</span>->beforeRender($viewFile, $<span>params</span>)) {<span>//</span><span>如果前置事件执行成功</span>
<span>261</span>             Yii::trace(<span>"</span><span>Rendering view file: $viewFile</span><span>"</span>, __METHOD__);<span>//</span><span>记录trace信息</span>
<span>262</span>             $ext = pathinfo($viewFile, PATHINFO_EXTENSION);<span>//</span><span>视图文件扩展名</span>
<span>263</span>             <span>if</span> (isset($<span>this</span>->renderers[$ext])) {<span>//</span><span>视图文件的扩展名是否支持</span>
<span>264</span>                 <span>if</span> (is_array($<span>this</span>->renderers[$ext]) || is_string($<span>this</span>-><span>renderers[$ext])) {
</span><span>265</span>                     $<span>this</span>->renderers[$ext] = Yii::createObject($<span>this</span>-><span>renderers[$ext]);
</span><span>266</span> <span>                }
</span><span>267</span>                 <span>/*</span><span> @var $renderer ViewRenderer </span><span>*/</span>
<span>268</span>                 $renderer = $<span>this</span>->renderers[$ext];<span>//</span><span>赋值view渲染器对象</span>
<span>269</span>                 $output = $renderer->render($<span>this</span>, $viewFile, $<span>params</span>);<span>//</span><span>渲染视图文件</span>
<span>270</span>             } <span>else</span> {<span>//</span><span>视图文件不是支持的类型,以普通php文件处理</span>
<span>271</span>                 $output = $<span>this</span>->renderPhpFile($viewFile, $<span>params</span><span>);
</span><span>272</span> <span>            }
</span><span>273</span>             $<span>this</span>->afterRender($viewFile, $<span>params</span><span>, $output);
</span><span>274</span> <span>        }
</span><span>275</span> 
<span>276</span>         array_pop($<span>this</span>-><span>_viewFiles);
</span><span>277</span>         $<span>this</span>->context =<span> $oldContext;
</span><span>278</span> 
<span>279</span>         <span>return</span><span> $output;
</span><span>280</span>     }

 

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn