構建本身的PHP框架--構建模版引擎(2)

自歷來到新公司就一直很忙,最近這段時間終於稍微閒了一點,趕忙接着寫這個系列,感受再不寫就爛尾了。php

以前咱們說到,拿到{{ $name }}這樣一段內容時,咱們只須要將它轉化成<?php echo $name ?>這樣,就能夠識別了,輸出相應的變量值。html

那就要須要正則匹配{{ $name }},而後替換掉{{}},分別替換成<?php echo?>git

可是要想到一個問題,若是我在 view 裏寫了 php 的代碼,其中含有{{ $name }},也會被替換。例子以下:github

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

要解決這個問題,咱們須要將 PHP 的代碼去掉,只留下 html 代碼再作替換的處理。幸虧 PHP 有一個方法 token_get_all,會將提供的內容按 PHP 標記進行分割。使用此方法解析以下內容:ui

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

<html>
  <body>{{ \$name }}</body>
<html>
VIEW;
print_r(token_get_all($content));

這裏$符號前加\是爲了轉移,在真正是現實不須要。結果以下:this

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 代碼。code

咱們定義view文件的後綴爲sf,那咱們就能夠在controller/model/view目錄下建立view.sf文件,內容以下orm

<?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方法,代碼以下htm

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以下blog

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

相關文章
相關標籤/搜索