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

发布于 2024-11-03 19:00:31 字数 747 浏览 1 评论 0原文

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

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

$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. 

I am trying to build a basic templating engine. Like the template engines already available as open source, I am using search and replace techniques.

However, as the search and replace have to be hardcoded, it is not so much flexible. What I mean to say is, as an example, I am using something like this

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

As you can see, it is hardcoded. So I have to purposely know all the placeholders to accomplish a successful render.

I am a little bit weak in regular expression. But I know, if I can develop a regex, which can match all the text starting with {_ and ending _} and get the value in between them, I just might be able to create a flexible templating engine.

I need help with the regular expression.

If I am completely going the wrong way to accomplish, please do warn me.


For those who think I am reinventing the wheel. Here is my explanation

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

并安 2024-11-10 19:00:31

如果您的模板标签只有一个单词,您要查找的正则表达式是 {_(\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-_] 表示它将匹配字母数字字符、连字符或下划线。

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

The regular expression you're looking for is {_(\w+)_}, if your template tags are only ever a single word. You'd use it a bit like this:

<?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;

?>

You'll see the preg_match_all has forward slashes surrounding the regular expression, these are delimiters.

Update: If you want to expand the regular expression beyond single words, then be careful when using . to match any character. It's better to use something like this to specify that you want to include other characters: {_([\w-_]+)_}. The [\w-_] means it will match either alphanumeric characters, hyphens or underscores.

(Perhaps someone can explain why using . might be a bad idea? I'm not 100% sure).

红ご颜醉 2024-11-10 19:00:31

除非您试图限制人们在模板中可以执行的操作并想要控制他们可以在其中放入哪些标记,否则我会推荐 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;

Unless you're trying to restrict down what people can do within a template and want to control what markup they can put in it I'd recommend PHP as a pretty kick-ass templating language!

If you want to stick with your solution you could do something like this to manage replacements.

$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;
揽月 2024-11-10 19:00:31

我结合了 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;

I have combined the solutions provided by both Sam and James to create a new solution.

  • Thanks to Sam for the regex part
  • Thanks to James for the array mode str_replace() part.

Here is the solution:

$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;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文