zoukankan      html  css  js  c++  java
  • 构建自己的PHP框架--构建模版引擎(2)

    自从来到新公司就一直很忙,最近这段时间终于稍微闲了一点,赶紧接着写这个系列,感觉再不写就烂尾了。

    之前我们说到,拿到{{ $name }}这样一段内容时,我们只需要将它转化成<?php echo $name ?>这样,就可以识别了,输出相应的变量值。

    那就要需要正则匹配{{ $name }},然后替换掉{{}},分别替换成<?php echo?>

    但是要想到一个问题,如果我在 view 里写了 php 的代码,其中含有{{ $name }},也会被替换。例子如下:

    <?php
    $name = 'test';
    $str = "{{ $name }}";
    ?>
    

    要解决这个问题,我们需要将 PHP 的代码去掉,只留下 html 代码再做替换的处理。幸好 PHP 有一个方法 token_get_all,会将提供的内容按 PHP 标记进行分割。使用此方法解析如下内容:

    $content = <<<VIEW
    <?php
    $name = 'test';
    $str = "{{ $name }}";
    ?>
    
    <html>
      <body>{{ $name }}</body>
    <html>
    VIEW;
    print_r(token_get_all($content));
    

    这里$符号前加是为了转移,在真正是现实不需要。结果如下:

    Array
    (
        [0] => Array
            (
                [0] => 379
                [1] => <?php
                [2] => 1
            )
        [1] => Array
            (
                [0] => 382
                [1] =>
                [2] => 2
            )
        [2] => =
        [3] => Array
            (
                [0] => 382
                [1] =>
                [2] => 2
            )
        [4] => Array
            (
                [0] => 323
                [1] => 'test'
                [2] => 2
            )
        [5] => ;
        [6] => Array
            (
                [0] => 382
                [1] =>
                [2] => 2
            )
        [7] => =
        [8] => Array
            (
                [0] => 382
                [1] =>
                [2] => 3
            )
        [9] => "
        [10] => Array
            (
                [0] => 322
                [1] => {{
                [2] => 3
            )
        [11] => Array
            (
                [0] => 320
                [1] => $name
                [2] => 3
            )
    
        [12] => Array
            (
                [0] => 322
                [1] =>  }}
                [2] => 3
            )
        [13] => "
        [14] => ;
        [15] => Array
            (
                [0] => 382
                [1] =>
                [2] => 3
            )
        [16] => Array
            (
                [0] => 381
                [1] => ?>
                [2] => 4
            )
        [17] => Array
            (
                [0] => 321
                [1] =>
    <html>
      <body>{{ $name }}</body>
    <html>
                [2] => 5
            )
    
    )
    

    可以看到 PHP 相关的代码被解析了,我们只需要判断出是 html 代码,然后做替换就可以了。其中的321就是定义好的常量T_INLINE_HTML的值,标记解析出来的就是 html 代码。

    我们定义view文件的后缀为sf,那我们就可以在controller/model/view目录下创建view.sf文件,内容如下

    <?php
    $title = 'It is a title';
    $str = "{{ $title }}";
    ?>
    
    <html>
        <head>
            <title>{{ $title }}</title>
        <head>
        <body>
            <h2>{{ $str }}</h2>
            <p>{{ $body }}<p>
        </body>
    </html>
    

    然后我们来改造Controller中的render方法,代码如下

    public function render($view, $params = [])
    {
        $file = '../views/' . $view . '.sf';
        $fileContent = file_get_contents($file);
        $result = '';
        foreach (token_get_all($fileContent) as $token) {
            if (is_array($token)) {
                list($id, $content) = $token;
                if ($id == T_INLINE_HTML) {
                    $content = preg_replace('/{{(.*)}}/', '<?php echo $1 ?>', $content);
                }
                $result .= $content;
            } else {
                $result .= $token;
            }
        }
        $generatedFile = '../runtime/cache/' . md5($file);
        file_put_contents($generatedFile, $result);
        extract($params);
        require_once $generatedFile;
    }
    

    修改actionView如下

    public function actionView()
    {
        $this->render('site/view', ['body' => 'Test body information']);
    }
    

    访问 http://localhost/simple-framework/public/index.php?r=site/view ,得到如下页面

    今天就先到这里。项目内容和博客内容也都会放到Github上,欢迎大家提建议。

    code:https://github.com/CraryPrimitiveMan/simple-framework/tree/1.1

    blog project:https://github.com/CraryPrimitiveMan/create-your-own-php-framework

  • 相关阅读:
    面向对象(五)-魔法方法
    面向对象(四)-实例,类,静态方法
    生成随机数
    vue中自己新建的组件怎么使用
    时间戳转时间
    js基础知识(一)--去除重复数据
    vue 实现底部导航栏
    dgl库:dgl._ffi.base.DGLError: [18:13:27] _func_ext.h:117: Check failed: ObjectTypeChecker<TObjectRef>::Check(sptr.get())
    DGL安装
    geopandas包安装
  • 原文地址:https://www.cnblogs.com/CraryPrimitiveMan/p/6964628.html
Copyright © 2011-2022 走看看