成分
每当我需要渲染一个“树枝”模板引擎页面时,我都需要这些组件。 $页面:我要渲染的模板的名称。 $模板层次结构:从$ Page One,...到te root模板。是的,因为在类似树枝的模板引擎中,模板可以扩展另一个。 $ CACH:因为存储缓存文件并将内容保存在缓存中很重要,而不是随时重新打开文件。最后但并非最不重要的$块:因为每个模板都可以覆盖父模板的块。
$page = 'page';
$hierarchy = [];
$cache = [];
$blocks = [];
等级制度
构建模板的层次结构非常简单。只需打开所需的页面,并检查extends
零件是否存在。查找父模板,直到模板不包含父。
同时,我构建了层次结构,我还存储所有需要的模板。我将在下一步中再次需要构建最终的渲染模板。缓存可以帮助我建立更好的表演。
do {
$hierarchy[] = $page;
$filename = __DIR__ . '/../templates/'.$page.'.engine';
$cache[$page] = file_get_contents($filename);
$re = '/extends \'([\w]{0,})\'/m';
preg_match_all($re, $cache[$page], $matches, PREG_SET_ORDER, 0);
if ($matches != []) {
$page = $matches[0][1];
}
} while ($matches != []);
块
现在我们有了模板的层次结构。我将模板的$层次结构从根模板开始。从这里返回到所需的模板,我可以检查是否必须重写某个块。
foreach(array_reverse($hierarchy) as $template) {
$re = '/ block ([\w<>\/ \n\s]{0,}) /m';
$content = $cache[$template];
preg_match_all($re, $content, $matches, PREG_SET_ORDER, 0);
$blockList = array_column($matches, 1);
foreach ($blockList as $block) {
$re = '/{% block '.$block.' %}([\{\}\[\]\w=\"\<\/\> \n\.]{0,}){% endblock '.$block.' %}/m';
preg_match_all($re, $content, $matches, PREG_SET_ORDER, 0);
if ($matches != []) {
$blocks[$block] = $matches[0][1];
}
}
}
现在我已经有一系列块。每个块包含每个块的最终版本。
渲染块
现在我将获得缓存的最后一项内容。记住?是根模板。现在,...我将使用“ Ultimate”块的数组呈现所有块。
$content = end($cache);
foreach($blocks as $name => $block) {
$re = '/{% block '.$name.' %}([\{\}\[\]\w=\"\<\/\> \n\.]{0,}){% endblock '.$name.' %}/m';
$content = preg_replace($re, $blocks[$name], $content);
}
变量
最后实现的功能是模型的渲染。像在树枝中一样,... {{foo}}
呈现foo变量。
$model = [ 'title' => 'titolo dal modello', ];
$re = '/{{([\w]{0,})}}/m';
preg_match_all($re, $content, $matches, PREG_SET_ORDER, 0);
foreach(array_unique(array_column($matches, 1)) as $var) {
$content = str_replace('{{'.$var.'}}', $model[$var], $content);
}
使成为, ...
现在,$content
包含渲染模板。只需打印
echo $content;
结论
好的,这是未经测试的代码。只是我可以使用RegexP进行的练习,并检查我是否能够构建这样的模板引擎。我相信我永远不会在生产中使用它。是练习。
关联
我制作的视频的链接在这里:I wrote twig in 50 lines of code。我以意大利语讲话的这段视频,但代码在php中。