创建一个简单但灵活的模板引擎

时间:2011-04-28 07:15:52

标签: php regex templating-engine

我正在尝试构建一个基本的模板引擎。就像已经作为开源提供的模板引擎一样,我正在使用搜索和替换技术。

但是,由于搜索和替换必须是硬编码的,因此它不是那么灵活。我的意思是,作为一个例子,我正在使用这样的东西

$templateMarkup = '<div class="title">{_TITLE_}</div>';
$renderedMarkup = str_replace("{_TITLE_}",$title,$templateMarkup);
echo $renderedMarkup;

正如您所看到的,它是硬编码的。因此,我必须故意了解所有占位符以完成成功渲染。

我在正则表达方面有点弱。但我知道,如果我可以开发一个正则表达式,它可以匹配所有以{_开头并结束_}的文本并获取它们之间的值,我就可以创建一个灵活的模板引擎。

我需要正则表达式的帮助。

如果我完全走错了路,请警告我。

<子> 对于那些认为我正在重新发明轮子的人。这是我的解释

Templating engines, that are already available are quite unnecessarily complex. 
My requirements are simple and so I am builidng my own simple engine. 

3 个答案:

答案 0 :(得分:2)

除非你试图限制人们在一个模板中可以做什么,并想控制他们可以放入哪个标记,否则我会推荐PHP作为一种漂亮的模板语言!

如果你想坚持你的解决方案,你可以做这样的事情来管理替换。

$template = "foo={_FOO_},bar={_BAR_},title={_TITLE_}\n";

$replacements = array(
    'title' => 'This is the title',
    'foo' => 'Footastic!',
    'bar' => 'Barbaric!'
);

function map($a) { return '{_'. strtoupper($a) .'_}';}

$keys = array_map("map", array_keys($replacements));
$rendered = str_replace($keys, array_values($replacements), $template);

echo $rendered;

答案 1 :(得分:1)

如果您的模板标记只是一个单词,那么您正在寻找的正则表达式为{_(\w+)_}。你有点像这样使用它:

<?php

$replacements = array(
    "firstname" => "John",
    "lastname" => "Smith"
);

$template_markup = "Hello {_firstname_} {_lastname_}";
if(preg_match_all('/{_(\w+)_}/', $template_markup, $matches)) {
    foreach($matches[1] as $m) {
        $template_markup = str_replace("{_".$m."_}", $replacements[$m], $template_markup);
    }
}
echo $template_markup;

?>

你会看到preg_match_all在正则表达式周围有正斜杠,这些都是分隔符。

更新:如果要将正则表达式扩展到单个单词之外,那么在使用.匹配任何字符时要小心。最好使用类似的东西来指定你想要包含其他字符:{_([\w-_]+)_}[\w-_]表示它将匹配字母数字字符,连字符或下划线。

(也许有人可以解释为什么使用.可能是一个坏主意?我不是百分百肯定的。)

答案 2 :(得分:0)

我结合了Sam和James提供的解决方案来创建新的解决方案。

  • 感谢 Sam 表示正则表达式部分
  • 感谢数组模式James部分 str_replace()

以下是解决方案:

$replacements = array(
    "firstname" => "John",
    "lastname" => "Smith"
);

function getVal($val) {
    global $replacements;
    return $replacements[$val];
}

$template_markup = "Hello {_firstname_} {_lastname_}";
preg_match_all('/{_(\w+)_}/', $template_markup, $matches);
$rendered = str_replace($matches[0], array_map("getVal",array_values($matches[1])), $template_markup);
echo $rendered;