简体   繁体   English

Laravel Blade 在幕后是如何工作的?

[英]How does Laravel Blade Work Behind the Scenes?

I have tried to find somewhere that explains this, but I can not find anything.我试图找到解释这一点的地方,但我找不到任何东西。

I really like one specific aspect of blade and that is the php echo tags {{ }}.我真的很喜欢 Blade 的一个特定方面,那就是 php echo 标签 {{ }}。 I am curious how I could go about duplicating the process this does on the backend.我很好奇我如何去复制这个在后端执行的过程。


An Idea I Tried我尝试过的想法


One idea I had is basically making a route like in laravel as show below.我的一个想法基本上是在 laravel 中制作一条路线,如下所示。

handler:处理程序:

Custom::Include('folder/index.custom.php');

index.custom.php: index.custom.php:

<custom>paragraph here</custom>

web browser:网页浏览器:

<div id="custom">paragraph here</custom>

The idea is my handler would be placed in the index page.这个想法是我的处理程序将被放置在索引页面中。 When it is called it would do file_get_contents , parse each line looking for custom tags, and then use a php echo to print the output.当它被调用时,它会做file_get_contents ,解析每一行寻找自定义标签,然后使用 php echo 打印输出。

This does work, however , the issue is when I get to php it can't work the same since it is server side and has passed by it once.这确实有效,但是,问题是当我使用 php 时,它无法正常工作,因为它是服务器端并且已经通过了一次。

This way also seems way to excessive to be on the right track.这种方式在正确的轨道上似乎也太过分了。 I added my idea in here was just to show how I have tried to duplicate the process.我在这里添加我的想法只是为了展示我如何尝试复制这个过程。


Does anyone have a simple explanation of how this is really done?有没有人对这是如何做到的有一个简单的解释?

You can play around output buffers along with file_get_contents and eval您可以使用file_get_contentseval来处理输出缓冲区

My dummy class:我的虚拟班级:

<?php

class Something
{

    public function getMatches($pattern, $string){
        preg_match_all($pattern, $string, $matches);        

        if(empty($matches[1]))
            return [];

        return $matches[1];
    }

    public function include($file){
        $contents = file_get_contents( $file);
        $contents = $this->execCodes($contents);

        echo $contents;
    }

    public function execCodes($contents){
        
        //match all @php code() @endphp
        $matches = $this->getMatches('/\@php(.*?)\@endphp/is', $contents);

        if(empty($matches))
            return $contents;

        $matches = array_unique($matches);

        foreach ($matches as $value) {
            
            //trim spaces
            $code = trim($value);

            $evaluatedCode = $this->getEvaluatedCode( $code ); //get output of evaluated code

            $code = $this->escapeRegExMetaChars($code);

            $pattern = "/(\@php.*?" . $code . '.*?\@endphp)/is'; //regex pattern for matching @php func() @endphp

            $contents = preg_replace($pattern, $evaluatedCode, $contents);  //replace all @php func() @endphp with evaluatedCode output

        }

        return $contents;

    }

    function escapeRegExMetaChars($string){

        $meta_chars = [ '\\', '^', '$', '.', '[', ']', '|', '(', ')', '?', '*', '+', '{', '}', '-', '\'', '/'];

        $len = strlen($string);
        $new_string = '';

        for($x = 0; $x < $len; $x++){

            if( in_array($string[$x], $meta_chars) ){
                $new_string .= '\\' . $string[$x];
            }else{
                $new_string .= $string[$x];
            }

        }
        
        return $new_string;

    }

    public function getEvaluatedCode(string $code){

        if(preg_match('/^(die|exit)/i', $code)){
            return "$code not allowed here";
        }

        //disable output buffers then return the ouput of the eval'ed code
        ob_start();
        eval($code);
        $output = ob_get_contents();
        ob_end_clean();

        return $output;

    }


}

?>

say test.html is liketest.html就像

<div>
    @php
        echo "Something";
    @endphp
</div>
<strong>
    This is a test
</strong>

Then:然后:

$some = new Something();
$some->include('test.html');

Output should be like:输出应该是这样的:

Something
This is a test 

You can do the same with @if @endif , @foreach @endforeach , {{ }} , etc you just need to do some more coding你可以对@if @endif@foreach @endforeach{{ }}等做同样的@endif ,你只需要做更多的编码

I think you're looking for custom blade directives.我认为您正在寻找自定义刀片指令。

The following example creates a @datetime($var) directive which formats a given $var , which should be an instance of DateTime :下面的例子创建了一个@datetime($var)指令,它格式化给定的$var ,它应该是DateTime一个实例:

<?php

namespace App\Providers;

use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
    /**
     * Perform post-registration booting of services.
     *
     * @return void
     */
    public function boot()
    {
        Blade::directive('datetime', function ($expression) {
            return "<?php echo ($expression)->format('m/d/Y H:i'); ?>";
        });
    }

    /**
     * Register bindings in the container.
     *
     * @return void
     */
    public function register()
    {
        //
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM