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

Posted

技术标签:

【中文标题】用 PHP 制作一个简单的模板引擎【英文标题】:Making a simple templating engine in PHP 【发布时间】:2021-03-13 18:42:24 【问题描述】:

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

示例:

String: "甚至还有奇怪的永恒 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

如何调整正则表达式和/或代码以解决双花括号?

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

【问题讨论】:

【参考方案1】:

你可以使用

$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]) 将 Group 1 值转换为小写,因为 $data 数组中的键都是小写的,$pattern 也可以匹配大写变体。

【讨论】:

聪明的解决方案。最重要的是,它奏效了!谢谢 如果键包含特殊字符,我建议使用array_map()preg_quote() 应用于array_keys($data) 如果值包含$1 或其他内容,则可能需要对赋予preg_replace_callback() 的值执行类似的操作。 @MonkeyZeus 如果有必要,我将在答案中添加implode("|", array_map(function($i) return preg_quote(trim($i), "/"); , array_keys($data))) 而不是implode('|', array_keys($data))。我怀疑nounverb,任何POS值都不止一个字母。 我真的无法预测 OP 的未来计划,但最好提前强化代码而不是尝试调试未来的问题,特别是如果 OP 不是将来维护代码的人。 【参考方案2】:

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

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

如果需要,您可以在 之前和 之后添加一个空格。

【讨论】:

【参考方案3】:

使用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' => 'biverbrd', 'verb' => 'fly'];

【讨论】:

strstr 是一个很好的解决方案,如果您可以控制数组键并将' 添加到它们。

以上是关于用 PHP 制作一个简单的模板引擎的主要内容,如果未能解决你的问题,请参考以下文章

一个简单的PHP模板引擎

PHP的常用的几大模板引擎

(10) PHP 随笔---Smarty模板引擎 布局/继承使用

论PHP模板的简单高效实现

PHP模板引擎smarty详细介绍

用 php 实现一个视图组件和模板引擎——基础