标签:
vendor\laravel\framework\src\Illuminate\View
是视图模块所在的文件夹,如未说明类所在文件位置则指此文件夹。
在使用视图相关的功能之前是需要做些准备的,准备自然是在服务提供者类运行的(在app\config.php
的providers中定义了应用中的服务提供者类),从中我们可以看出Illuminate\View\ViewServiceProvider::class
指的就是ViewServiceProvider
类,因此在ViewServiceProvider
类中会注册一些需要用到的依赖到容器,注入名称和实例如下:
view.engine.resolver EngineResolver
php PhpEngine
blade CompilerEngine
blade.compiler BladeCompiler
view.finder FileViewFinder
view Factory
这个时候我们已经可以看出Factory
是视图模块重要的类了,因为Laravel会从容器中取出view.engine.resolver, view.finder, events(这个类是其他地方注入到容器中的)中的对象作为参数传递给Factory
,而php和blade虽然并没有注入到容器,却是作为EngineResolver
的属性$resolvers
的值的。
上一步骤只是做了些视图运行前的准备,而并没有真的运行视图的功能,一般运行是从view()
开始的,这是一个全局的方法,这个方法是定义在vendor\laravel\framework\src\Illuminate\Foundation\helpers.php
中的,这里其实调用了Factory
的make()
,这个方法其实主要是对传入的参数做处理并用这些参数初始化View
类,再返回View
的实例。
$this->callCreator($view = new View($this, $this->getEngineFromPath($path), $view, $path, $data)); return $view;
对View
的处理还涉及到Router
和Response
的处理,不理会这个我们是知道视图其实返回的应该是字符串的才对。对象转字符串自然使用的是魔术方法__toString()
,这里并不直接返回字符串,而是通过一系列的调用最终是在getContents()
中返回$this->engine->get()
,这里的engine是CompilerEngine
,即上面View实例化的时候传递的第二个参数(也是EngineInterface
的实现),因为Laravel的视图文件的名称包含blade,所以实例化的是CompilerEngine
。事实上这和容器中名为view.engine.resolver的类实例有关,具体细节可以在getEngineFromPath()
中找。
CompilerEngine
的$compiler
才是实际把视图文件转成字符串的主力。一般的$compiler
的实例是BladeCompiler
,这个就是把Blade语法(Blade是Laravel内置模版引擎的名字)转换成PHP语法的核心。
不管上面的步骤如何的绕来绕去,把视图文件编译成字符串才是BladeCompiler
类的主场功能,这个类才是真正的苦力工作者。BladeCompiler
实现了CompilerInterface
接口,这个接口真正工作是compile()
,compile()
把视图文件编译成PHP的原生语法的字符串并写入到缓存目录的文件中,而getCompiledPath()
根据视图文件的路径来获取编译后的文件的路径。
编译使用token_get_all()
来进行语法的解析,当碰到PHP标记为T_INLINE_HTML
(T_INLINE_HTML
标记其实就是code无法直接解析成PHP而把这段code当作一段嵌套的HTML,这里一般就是指Blade语法的Code)的PHP标记时用对应的方法进行语法的替换,直到最终没有PHP标记为T_INLINE_HTML
为止。
无法直接编译的code分为4类,分别是扩展,语句,注释,输出,这个从$compilers
中可以看出,我们可以称$compilers
为内部编译器,每个内部编译器对应一个相应的解析方式,如注释编译器对应compileComments()
。
/** * Compile Blade comments into valid PHP. * * @param string $value * @return string */ protected function compileComments($value) { $pattern = sprintf(‘/%s--((.|\s)*?)--%s/‘, $this->contentTags[0], $this->contentTags[1]); return preg_replace($pattern, ‘<?php /*$1*/ ?>‘, $value); }
这里就把Blade语法的code{{-- This comment will not be present in the rendered HTML --}}
变成原生PHP语法的code<?php /*This comment will not be present in the rendered HTML*/ ?>
了。 从中不难看出就是把Blade语法翻译成PHP原生语法的实现。当然这是最简单的内部编译器,像语句,输出内部编译器的实现就复杂的多,但只是实现复杂,涉及到正则的解析和不同形式的语句的解析,原理还是一样的。
标签:
原文地址:http://www.cnblogs.com/icyse/p/4793599.html