用 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
,并且在捕获单词本身时将匹配双括号内的noun
或verb
。替换将是$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))
。我怀疑noun
,verb
,任何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 制作一个简单的模板引擎的主要内容,如果未能解决你的问题,请参考以下文章