zoukankan      html  css  js  c++  java
  • Laravel 视图模块运行流程

    提示:

    vendorlaravelframeworksrcIlluminateView是视图模块所在的文件夹,如未说明类所在文件位置则指此文件夹。

    1. 服务提供者类注入相关类到容器

    在使用视图相关的功能之前是需要做些准备的,准备自然是在服务提供者类运行的(在appconfig.php的providers中定义了应用中的服务提供者类),从中我们可以看出IlluminateViewViewServiceProvider::class指的就是ViewServiceProvider类,因此在ViewServiceProvider类中会注册一些需要用到的依赖到容器,注入名称和实例如下:

    view.engine.resolver  EngineResolver
        php               PhpEngine
        blade             CompilerEngine
    blade.compiler        BladeCompiler
    view.finder           FileViewFinder
    view                  Factory
    file
    这个时候我们已经可以看出Factory是视图模块重要的类了,因为Laravel会从容器中取出view.engine.resolver, view.finder, events(这个类是其他地方注入到容器中的)中的对象作为参数传递给Factory,而php和blade虽然并没有注入到容器,却是作为EngineResolver的属性$resolvers的值的。

    2.开始使用视图

    上一步骤只是做了些视图运行前的准备,而并没有真的运行视图的功能,一般运行是从view()开始的,这是一个全局的方法,这个方法是定义在vendorlaravelframeworksrcIlluminateFoundationhelpers.php中的,这里其实调用了Factorymake(),这个方法其实主要是对传入的参数做处理并用这些参数初始化View类,再返回View的实例。

    $this->callCreator($view = new View($this, $this->getEngineFromPath($path), $view, $path, $data));
    return $view;

    View的处理还涉及到RouterResponse的处理,不理会这个我们是知道视图其实返回的应该是字符串的才对。对象转字符串自然使用的是魔术方法__toString(),这里并不直接返回字符串,而是通过一系列的调用最终是在getContents()中返回$this->engine->get(),这里的engine是CompilerEngine,即上面View实例化的时候传递的第二个参数(也是EngineInterface的实现),因为Laravel的视图文件的名称包含blade,所以实例化的是CompilerEngine。事实上这和容器中名为view.engine.resolver的类实例有关,具体细节可以在getEngineFromPath()中找。

    3.模版的编译

    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原生语法的实现。当然这是最简单的内部编译器,像语句,输出内部编译器的实现就复杂的多,但只是实现复杂,涉及到正则的解析和不同形式的语句的解析,原理还是一样的。
     
  • 相关阅读:
    Python实现客观赋权法
    Python实现熵值法确定权重
    正则化项L1和L2
    特征工程的归一化和标准化
    CentOS下Neo4j安装教程
    Window下Neo4j安装教程
    Window下JDK安装教程
    Git 命令
    Kubernetes 资源清单 常用字段,Pod 实例
    kubernetes 集群搭建
  • 原文地址:https://www.cnblogs.com/icyse/p/4793599.html
Copyright © 2011-2022 走看看