以前大家兑现了最简便易行的echo
命令的沙盘替换,便是将{{ $name }}
这样一段内容替换到<?php echo $name ?>
。
当今大家的话下任何的吩咐,先来回看下此前的概念
- 出口变量值
{{ }}
表明式的再次回到值将被电动传送给 PHP
的 htmlentities
函数实行管理,以堤防 XSS
攻击。
Hello, {{ $name }}!
-
出口未转义的变量值
Hello, {!! $name !!}!
-
If 表达式
通过 @if
、@elseif
、@else
和 @endif
指令能够创制 if
表达式。
@if (count($records) === 1)
I have one record!
@elseif (count($records) > 1)
I have multiple records!
@else
I don't have any records!
@endif
-
循环
@for ($i = 0; $i < 10; $i++)
The current value is {{ $i }}
@endfor
@foreach ($users as $user)
<p>This is user {{ $user->id }}</p>
@endforeach
@while (true)
<p>I'm looping forever.</p>
@endwhile
-
引进别的视图
@include(‘view.name’, [‘some’ => ‘data’])
要协作这么些概念,大家要写出相应的正则表明式,关于@
始发的命令直接拿了laravel
中的使用。
大家先在src
下创建view
文件夹,再创建Compiler
类文件。
咱俩将compiler的艺术氛围二种,一种是@
开头的通令(Statements
),一种是出口(Echos
)。那二种的正则是不一样的。
率先定义变量compliers
,定义如下:
protected $compilers = [
'Statements',
'Echos',
];
然后按着见原本Controller
中render
艺术的剧情迁移到Complier
类中,按那三种依次相称,代码如下:
public function compile($path = null)
{
$fileContent = file_get_contents($path);
$result = '';
foreach (token_get_all($fileContent) as $token) {
if (is_array($token)) {
list($id, $content) = $token;
if ($id == T_INLINE_HTML) {
foreach ($this->compilers as $type) {
$content = $this->{"compile{$type}"}($content);
}
}
$result .= $content;
} else {
$result .= $token;
}
}
$generatedFile = '../runtime/cache/' . md5($path);
file_put_contents($generatedFile, $result);
require_once $generatedFile;
}
protected function compileStatements($content)
{
return $content;
}
protected function compileEchos($content)
{
return preg_replace('/{{(.*)}}/', '<?php echo $1 ?>', $content);
}
其中的Statements
统统未有管理,Echos
则依然跟以前同样。
先来调度下Echos
中的管理,增添变量记录{{ }}
和{!! !!}
的名称
protected $echoCompilers = [
'RawEchos',
'EscapedEchos'
];
管理的时候能够增加一下存在的推断,暗许值是null
,内容能够调动如下:
protected function compileEchos($content)
{
foreach ($this->echoCompilers as $type) {
$content = $this->{"compile{$type}"}($content);
}
return $content;
}
protected function compileEscapedEchos($content)
{
return preg_replace('/{{(.*)}}/', '<?php echo htmlentities(isset($1) ? $1 : null) ?>', $content);
}
protected function compileRawEchos($content)
{
return preg_replace('/{!!(.*)!!}/', '<?php echo isset($1) ? $1 : null ?>', $content);
}
EscapedEchos
和RawEchos
的区分在于,第叁个会做html
转义。
小编们再来看Statements
一声令下的管理,其原理也一律,相称到相应的通令,如if
、foreach
,调用相应的主意做替换。
代码如下:
protected function compileStatements($content)
{
return preg_replace_callback(
'/\B@(@?\w+(?:::\w+)?)([ \t]*)(\( ( (?>[^()]+) | (?3) )* \))?/x', function ($match) {
return $this->compileStatement($match);
}, $content
);
}
protected function compileStatement($match)
{
if (strpos($match[1], '@') !== false) {
$match[0] = isset($match[3]) ? $match[1].$match[3] : $match[1];
} elseif (method_exists($this, $method = 'compile'.ucfirst($match[1]))) {
$match[0] = $this->$method(isset($match[3]) ? $match[3] : null);
}
return isset($match[3]) ? $match[0] : $match[0].$match[2];
}
protected function compileIf($expression)
{
return "<?php if{$expression}: ?>";
}
protected function compileElseif($expression)
{
return "<?php elseif{$expression}: ?>";
}
protected function compileElse($expression)
{
return "<?php else{$expression}: ?>";
}
protected function compileEndif($expression)
{
return '<?php endif; ?>';
}
protected function compileFor($expression)
{
return "<?php for{$expression}: ?>";
}
protected function compileEndfor($expression)
{
return '<?php endfor; ?>';
}
protected function compileForeach($expression)
{
return "<?php foreach{$expression}: ?>";
}
protected function compileEndforeach($expression)
{
return '<?php endforeach; ?>';
}
protected function compileWhile($expression)
{
return "<?php while{$expression}: ?>";
}
protected function compileEndwhile($expression)
{
return '<?php endwhile; ?>';
}
protected function compileContinue($expression)
{
return '<?php continue; ?>';
}
protected function compileBreak($expression)
{
return '<?php break; ?>';
}
其中的include
落到实处相比费劲,就一直不做,留给我们想想啦。
然后,大家再思量一下,不只怕每一遍都去操作文件再一次生成,作者应该要看清文件退换,若是没退换一向动用缓存就足以了。
调动代码如下:
public function isExpired($path)
{
$compiled = $this->getCompiledPath($path);
if (!file_exists($compiled)) {
return true;
}
return filemtime($path) >= filemtime($compiled);
}
protected function getCompiledPath($path)
{
return '../runtime/cache/' . md5($path);
}
public function compile($file = null, $params = [])
{
$path = '../views/' . $file . '.sf';
extract($params);
if (!$this->isExpired($path)) {
$compiled = $this->getCompiledPath($path);
require_once $compiled;
return;
}
$fileContent = file_get_contents($path);
$result = '';
foreach (token_get_all($fileContent) as $token) {
if (is_array($token)) {
list($id, $content) = $token;
if ($id == T_INLINE_HTML) {
foreach ($this->compilers as $type) {
$content = $this->{"compile{$type}"}($content);
}
}
$result .= $content;
} else {
$result .= $token;
}
}
$compiled = $this->getCompiledPath($path);
file_put_contents($compiled, $result);
require_once $compiled;
}
这些种类的博客到这里就一时半刻告一段落了~
品类内容和博客内容也都会放到Github上,迎接我们提建议。
code:https://github.com/CraryPrimitiveMan/simple-framework/tree/1.2
blog
project:https://github.com/CraryPrimitiveMan/create-your-own-php-framework