在 PHP 中制作一个简单的模板引擎

Making a simple templating engine in PHP

我需要编写一个简单的 PHP 函数来用各自的数据替换 {{ }} 个字符之间的文本。

示例:

字符串:“甚至还有奇怪的万世 {{noun}} 可能 {{verb}}

$data = ['noun' => 'bird', 'verb' => 'fly'];

结果:

"甚至 都可以"

我几乎可以使用基于 preg_replace_callback

的以下代码
function compile($str,$data){

    foreach ($data as $k => $v) {
        $pattern = '/\b(?<!\-)(' . $k . ')\b(?!-)/i';
        $str = preg_replace_callback($pattern, function($m) use($v){
            return $v;
        }, $str);
    }

    return $str;
}

但我似乎无法解释 {{ }}

结果如下所示:

"并且随着奇怪的永世甚至 {{bird}} 可能 {{fly}}"

如何调整正则表达式 and/or 代码以解决双大括号?

此外,在有人问我为什么要尝试手动执行此操作而不是使用 PHP 本身或 Smarty 插件之前——安装插件的用例太窄了,我不能使用 PHP 本身,因为输入字符串作为数据库中的原始文本传入。我需要使用存储在 PHP 数组中的数据来编译原始文本。

您可以使用

$str = "and with strange aeons even {{noun}} may {{verb}}";
$data = ['noun' => 'bird', 'verb' => 'fly'];

$pattern = '/{{(' . implode('|', array_keys($data)) . ')}}/i';
echo preg_replace_callback($pattern, function($m) use($data){
    return $data[strtolower($m[1])];
}, $str);
// => and with strange aeons even bird may fly

参见PHP demo

$pattern 看起来像 /{{(noun|verb)}}/i,并且会在捕获单词本身时匹配双括号内的 nounverb。替换将是 $data 数组的相应键值。需要使用 strtolower($m[1]) 将第 1 组值变为小写,因为 $data 数组中的键都是小写,并且 $pattern 也可以匹配大写变体。

既然你在循环,请保持简单:

foreach ($data as $k => $v) {
    $str = str_ireplace('{{'.$k.'}}', $v, $str);
}

如果需要,您可以在 {{ 之前和 }} 之后添加 space。

利用 strtr() 收工:

$string = 'and with strange aeons even {{noun}} may {{verb}}';

$data = ['{{noun}}' => 'bird', '{{verb}}' => 'fly'];

echo strtr( $string, $data );

产生:

and with strange aeons even bird may fly

strtr() 很好,因为它不会在以下情况下弄乱字符串:

$data = ['{{noun}}' => 'bi{{verb}}rd', '{{verb}}' => 'fly'];