찾다
백엔드 개발PHP 튜토리얼Laravel 模板引擎(Blade)原理简析

上次提到过,模板引擎一般是要做三件事情:

  • 变量值的输出(echo)

  • 条件判断和循环(if ... else、for、foreach、while)

  • 引入或继承其他文件

  • 现在就来看看 Laravel 的模板引擎是如何来处理这三件事情的。我是在 Laravel 5.1 的实现上来写这篇文章的。

    1. 视图解析流程

    Laravel 的 View 部分是内置了两套输出系统:直接输出和使用 Blade 引擎“编译”后输出,默认情况下它们通过文件名后缀来选择:.blade.php 后缀的认为是模板视图文件,其他的 .php 文件按照 PHP 本身的方式执行。虽然 Blade 模板文件中也可以随意嵌入 PHP 代码,但如果并没有使用,系统还去进行语法解析和替换也是没有必要的,这样可以提高效率。

    在使用 View 组件输出时,不管是调用 helpers 中提供的 view 函数还是使用 Facades 提供静态接口 View::make(),实际上执行的都是 Illuminate\View\Factory 中的 make 方法。以此为入口,很容易就能知道视图解析输出的流程:

  • 查找视图文件;

  • 根据文件名后缀从 Container 中取出响应的引擎;

  • 加载视图文件或编译后加载编译后的文件执行,同时将需要解析的数据暴露在视图文件环境中。

  • Factory 中的一些方法完成了以上第一步的过程,文件查找是调用的 FileViewFinder,其中使用了一些 Illuminate\Filesystem\Filesystem 中的方法,这个类中还有一些方法是跟 events 相关的,这里就忽略不表了。

    在以上步骤中,如果中获取到的视图文件是需要“编译”的,引擎会调用 “Blade 编译器”将原视图进行“编译”并保存在 cache 目录中然后加载输出。下次调用时如果发现源文件并没有被修改过就不再重新编译而是直接获取缓存文件并输出。

    CompilerEngine 调用的编译器是 CompilerInterface 接口的实现,默认情况下也就只有 BladeCompiler(如果不知道解析器是如何注入的,你需要去了解 Laravel 的服务容器,这里就不细表)。

    2. Blade 引擎

    接下来就是本文的重点:Blade 是如何“编译”的。我一直给“编译”两个字加引号,因为这显然不是真正意义上的代码编译的过程,只是一些正则替换的过程。

    我们知道 Laravel 的模板引擎是很简洁的,使用时并不需要掌握太多东西,基本上只需要知道以下两点:

  • {{ 与 }} 之间是要输出的内容,也有扩展的两个方法 {{{ ... }}} 和 {!! .. !!} 分别用于转义输出和不转义输出,5.0 以后的版本中 {{ ... }} 之间的默认情况下也是转义处处的;

  • @ 符号开头的都是指令,包括 PHP 本身有的 if else foreach 以及扩展的 include yield stop 等等;

  • 而 Blade 对于解析的处理实际上是分了四种情况:

  • Extensions -> 扩展部分

  • Statements -> 语句块(就是 @ 开头的指令)

  • Comments -> 注释部分({{-- ... --}} 的写法,解析之后是 PHP 的注释而不是 HTML的注释)

  • Echos -> 输出

  • 在解析(解析是在 cache 不存在的情况下)过程中,Blade 会先使用 token_get_all 函数获取到视图文件中的被 PHP 解释器认为是 HTML(T_INLINE_HTML)的部分,然后依次进行以上四种情况的解析。

    扩展部分是调用用户自定义的编译器解析字符串。BladeCompiler 中提供了的 extend 方法来添加可扩展。

    注释部分也很简单,就是将 {{-- ... --}} 替换成

    输出部分提供了三个方法,分别对应上文提到的三种情况:

  • compileRawEchos -> 输出未经转义的内容 ({!! ... !!})

  • compileEscapedEchos -> 输出转义之后的内容 ({{{ ... }}})

  • compileRegularEchos -> 正常输出 ({{ ... }})

  • 默认情况下经过字符替换之后 compileEscapedEchos 和 compileRegularEchos 的函数体其实是完全一样的,在输出的时候都是调用一个 e() 的辅助函数来输出:

    <?php    function e($value)    {        if ($value instanceof Htmlable) {            return $value->toHtml();        }        return htmlentities($value, ENT_QUOTES, 'UTF-8', false);    }

    这貌似是 5.0 之后的版本才改的,之前的版本里 compileRegularEchos 执行的是 compileRawEchos 的行为。不过两个函数还是有一个区别:compileRegularEchos 的转义函数是可以通过 setEchoFormat 自定义的(只是默认是 e()),但是 compileEscapedEchos 不允许自定义。

    echo 后的内容也是经过正则替换的:

    <?php    public function compileEchoDefaults($value)    {        return preg_replace('/^(?=\$)(.+?)(?:\s+or\s+)(.+?)$/s', 'isset($1) ? $1 : $2', $value);    }

    从正则表达式中可以看出来输出提供了一个 or 的关键字,$a or $b 的写法会被替换成 isset($a) ? $a : $b。

    语句块部分可以分成三种情况:

  • 和 PHP 本身一样的 if else foreach 以及扩展的 unless 等流程和循环控制的关键字;

  • include yield 等模板文件引入、内容替换的部分;

  • lang choice can 等涉及到 Laravel 其他组件的功能性关键字。

  • 第一种情况是很简单的替换过程,本身 PHP 为了在 HMTL 和 PHP 混合书写方便就提供了 if foreach 等几个关键字使用冒号和 endif 等关键字代替大括号来控制流程的方法。

    第二种情况稍微复杂一点,比如下面的函数:

    <?php    protected function compileYield($expression)    {        return "<?php echo \$__env->yieldContent{$expression}; ?>";    }

    解析之后的语句是调用了一个名为 $_env 的实例中的方法。这个实例其实就是 Illuminate\View\Factory 的实例:

    Factory 的构造函数:

    <?php    public function __construct(EngineResolver $engines, ViewFinderInterface $finder, Dispatcher $events)    {        ...        $this->share('__env', $this);    }

    Illuminate\View\View 中:

    <?php    protected function getContents()    {        return $this->engine->get($this->path, $this->gatherData());    }    /**     * Get the data bound to the view instance.     *     * @return array     */    protected function gatherData()    {        $data = array_merge($this->factory->getShared(), $this->data);        ...        return $data;    }

    由此也可以看出 each yield 等指令的实现也是在 Factory 中,分别对应的是 renderEach yieldContent 等。

    所以文件引入等指令的实现方式就是:在主视图输出的时候,通过注入的 $__env 来重复调用 Factory 中的 make 方法来输出引入的文件。

    至于 lang 等关键字,替换后就是使用 app() 函数来调用 Laravel 的其他组件。此外 Blade 还提供了 inject 关键字来调用任何你想使用的组件。

    除了以上这些,你还可以通过 directive 方法来增加一些自定义指令。

    compileStatements 方法中最后进行正则替换的正则表达式看起来比较复杂:

    /\B@(\w+)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x

    这是因为正则后面的一部分实现了递归模式来匹配语句块中括号的数量。

    3. 后话

    通过以上的分析可以看出来 Laravel 的视图组件还是十分简洁的,同时也不失灵活性和可扩展性。如果有兴趣的话,也可以实现一个自己的模板解析引擎。

    如果你想在其他项目中使用 Blade 引擎,通过 Composer 安装下来之后会发现还有 Container、Events 等部分,这和 Laravel 本身有关。

    为了能够在任何地方使用 Blade,我把它核心的部分提取了出来,去掉了其他组件的依赖,也不再依赖文件扩展名来选择引擎:

    项目地址:https://github.com/XiaoLer/blade

    此外也通过这个提取之后的版本做了一个 yii2 能够使用的版本:https://github.com/XiaoLer/yii2-blade。在之前尝试的版本中直接使用 Laravel 的 View 组件并不灵活,现在感觉好多了。

    个人博客原文:http://0x1.im/blog/laravel/laravel-blade-engine.html

    성명
    본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
    PHP 세션에 저장된 데이터를 어떻게 수정합니까?PHP 세션에 저장된 데이터를 어떻게 수정합니까?Apr 27, 2025 am 12:23 AM

    tomodifyDatainAphPessess, startSessionstession_start (), 그런 다음 $ _sessionToset, modify, orremovevariables.

    PHP 세션에 배열을 저장하는 예를 제시하십시오.PHP 세션에 배열을 저장하는 예를 제시하십시오.Apr 27, 2025 am 12:20 AM

    배열은 PHP 세션에 저장할 수 있습니다. 1. 세션을 시작하고 session_start ()를 사용하십시오. 2. 배열을 만들고 $ _session에 저장하십시오. 3. $ _session을 통해 배열을 검색하십시오. 4. 세션 데이터를 최적화하여 성능을 향상시킵니다.

    Garbage Collection은 PHP 세션에 어떻게 효과가 있습니까?Garbage Collection은 PHP 세션에 어떻게 효과가 있습니까?Apr 27, 2025 am 12:19 AM

    PHP 세션 쓰레기 수집은 만료 된 세션 데이터를 정리하기위한 확률 메커니즘을 통해 트리거됩니다. 1) 구성 파일에서 트리거 확률 및 세션 수명주기를 설정합니다. 2) CRON 작업을 사용하여 고재 응용 프로그램을 최적화 할 수 있습니다. 3) 데이터 손실을 피하기 위해 쓰레기 수집 빈도 및 성능의 균형을 맞춰야합니다.

    PHP에서 세션 활동을 어떻게 추적 할 수 있습니까?PHP에서 세션 활동을 어떻게 추적 할 수 있습니까?Apr 27, 2025 am 12:10 AM

    PHP의 사용자 세션 활동 추적은 세션 관리를 통해 구현됩니다. 1) Session_start ()를 사용하여 세션을 시작하십시오. 2) $ _session 배열을 통해 데이터를 저장하고 액세스하십시오. 3) 세션 _destroy ()를 호출하여 세션을 종료합니다. 세션 추적은 사용자 행동 분석, 보안 모니터링 및 성능 최적화에 사용됩니다.

    데이터베이스를 사용하여 PHP 세션 데이터를 저장할 수있는 방법은 무엇입니까?데이터베이스를 사용하여 PHP 세션 데이터를 저장할 수있는 방법은 무엇입니까?Apr 27, 2025 am 12:02 AM

    데이터베이스를 사용하여 PHP 세션 데이터를 저장하면 성능 및 확장 성을 향상시킬 수 있습니다. 1) 세션 데이터를 저장하기 위해 MySQL 구성 : php.ini 또는 php 코드에서 세션 프로세서를 설정하십시오. 2) 사용자 정의 세션 프로세서 구현 : 데이터베이스와 상호 작용하기 위해 열린, 닫기, 읽기, 쓰기 및 기타 기능을 정의합니다. 3) 최적화 및 모범 사례 : 인덱싱, 캐싱, 데이터 압축 및 분산 스토리지를 사용하여 성능을 향상시킵니다.

    PHP 세션의 개념을 간단한 용어로 설명하십시오.PHP 세션의 개념을 간단한 용어로 설명하십시오.Apr 26, 2025 am 12:09 AM

    phpsessionstrackuserdataacrossmultiplepagerequestsususingauniqueIdStoredInAcookie.here'showtomanagetheMeftically : 1) STARTASESSIONSTART_START () andSTAREDATAIN $ _SESSION.2) RegenerATERATESSESSIDIDAFTERLOGINWITHSESSION_RATERATERATES (True) TopreventSES

    PHP 세션에 저장된 모든 값을 어떻게 반복합니까?PHP 세션에 저장된 모든 값을 어떻게 반복합니까?Apr 26, 2025 am 12:06 AM

    PHP에서 세션 데이터를 통한 반복은 다음 단계를 통해 달성 할 수 있습니다. 1. Session_start ()를 사용하여 세션을 시작하십시오. 2. $ _session 배열의 모든 키 값 쌍을 통해 Foreach 루프를 통과합니다. 3. 복잡한 데이터 구조를 처리 할 때 is_array () 또는 is_object () 함수를 사용하고 print_r ()를 사용하여 자세한 정보를 출력하십시오. 4. Traversal을 최적화 할 때 페이징을 사용하여 한 번에 많은 양의 데이터를 처리하지 않도록 할 수 있습니다. 이를 통해 실제 프로젝트에서 PHP 세션 데이터를보다 효율적으로 관리하고 사용하는 데 도움이됩니다.

    사용자 인증에 세션을 사용하는 방법을 설명하십시오.사용자 인증에 세션을 사용하는 방법을 설명하십시오.Apr 26, 2025 am 12:04 AM

    이 세션은 서버 측 상태 관리 메커니즘을 통해 사용자 인증을 인식합니다. 1) 세션 생성 및 고유 ID의 세션 생성, 2) ID는 쿠키를 통해 전달됩니다. 3) ID를 통해 서버 저장 및 세션 데이터에 액세스합니다. 4) 사용자 인증 및 상태 관리가 실현되어 응용 프로그램 보안 및 사용자 경험이 향상됩니다.

    See all articles

    핫 AI 도구

    Undresser.AI Undress

    Undresser.AI Undress

    사실적인 누드 사진을 만들기 위한 AI 기반 앱

    AI Clothes Remover

    AI Clothes Remover

    사진에서 옷을 제거하는 온라인 AI 도구입니다.

    Undress AI Tool

    Undress AI Tool

    무료로 이미지를 벗다

    Clothoff.io

    Clothoff.io

    AI 옷 제거제

    Video Face Swap

    Video Face Swap

    완전히 무료인 AI 얼굴 교환 도구를 사용하여 모든 비디오의 얼굴을 쉽게 바꾸세요!

    뜨거운 도구

    SublimeText3 Mac 버전

    SublimeText3 Mac 버전

    신 수준의 코드 편집 소프트웨어(SublimeText3)

    DVWA

    DVWA

    DVWA(Damn Vulnerable Web App)는 매우 취약한 PHP/MySQL 웹 애플리케이션입니다. 주요 목표는 보안 전문가가 법적 환경에서 자신의 기술과 도구를 테스트하고, 웹 개발자가 웹 응용 프로그램 보안 프로세스를 더 잘 이해할 수 있도록 돕고, 교사/학생이 교실 환경 웹 응용 프로그램에서 가르치고 배울 수 있도록 돕는 것입니다. 보안. DVWA의 목표는 다양한 난이도의 간단하고 간단한 인터페이스를 통해 가장 일반적인 웹 취약점 중 일부를 연습하는 것입니다. 이 소프트웨어는

    에디트플러스 중국어 크랙 버전

    에디트플러스 중국어 크랙 버전

    작은 크기, 구문 강조, 코드 프롬프트 기능을 지원하지 않음

    SecList

    SecList

    SecLists는 최고의 보안 테스터의 동반자입니다. 보안 평가 시 자주 사용되는 다양한 유형의 목록을 한 곳에 모아 놓은 것입니다. SecLists는 보안 테스터에게 필요할 수 있는 모든 목록을 편리하게 제공하여 보안 테스트를 더욱 효율적이고 생산적으로 만드는 데 도움이 됩니다. 목록 유형에는 사용자 이름, 비밀번호, URL, 퍼징 페이로드, 민감한 데이터 패턴, 웹 셸 등이 포함됩니다. 테스터는 이 저장소를 새로운 테스트 시스템으로 간단히 가져올 수 있으며 필요한 모든 유형의 목록에 액세스할 수 있습니다.

    WebStorm Mac 버전

    WebStorm Mac 버전

    유용한 JavaScript 개발 도구