您的位置:首页 > 编程语言 > PHP开发

构建自己的PHP框架--构建模版引擎(2)

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

之前我们说到,拿到
{{ $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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: