我知道答案可能很简单,我只是没有看到。这段代码使我在布局中(例如[[tag]]
)放置了一个“标签”数组,并且请求($this->data
)附带了一个替换数组。我的第一个倾向是使用preg_match_all
获取所有标签的数组,然后只传入两个数组:
if(isset($this->layout))
{
ob_start();
include(VIEWS.'layouts/'.$this->layout.'.phtml');
$this->layout = ob_get_contents();
preg_match_all('/\[\[.*\]\]/', $this->layout, $tags);
print preg_replace($tags, $this->data, $this->layout);
}
但是阵列的长度(大部分时间)不同。该布局可能会重用某些标签,并且传入的数据变量可能在布局中不包含某些标签。
[我觉得必须有一种比执行foreach
并通过迭代构建输出更有效的方法。
该项目规模太小,无法实现像Smarty或Twig这样的完整模板引擎。它实际上只是几页纸和一些替代品。我的客户只想要一种简单的方法来添加页面标题和电子邮件收件人等内容。
任何建议将不胜感激。就像我说的那样,我很肯定我忽略了这件事。
编辑:$this->data
是替换文本的数组,看起来像:
tag => replacement_text
编辑2:如果我使用preg_match_all('/\[\[(.*)\]\]/', $this->layout, $tags);
,则该数组仅包含标签(没有[[]]
),我只需要一种方法即可将它们与$this->data
中的替换字符串数组进行匹配。
您可以简单地使用str_replace
来完成这项工作,从str_replace
中创建搜索字符串和替换字符串的数组:
$this->data
$search = array_map(function ($s) { return "[[$s]]"; }, array_keys($this->data));
$replacements = array_values($this->data);
echo str_replace($search, $replacements, $this->layout);
您不需要通过匹配Demo on 3v4l.org来获得$tags
,该信息全部在$this->layout
的键中。您只需要在按键周围添加$this->data
。
[[...]]
另一种解决方法是使用$tags = array_map(function($key) {
return '/\[\[' . preg_quote($key) . '\]\]';
}, array_keys($this->data));
在preg_replace_callback()
中查找标签;
$this->data
请注意,我将正则表达式更改为使用非贪婪的量词;您的正则表达式将从第一个标签的开头到最后一个标签的结尾匹配。
如果在echo preg_replace_callback('/\[\[(.*?)\]\]/', function($matches) {
return $this->data[$matches[1]] ?? $matches[0];
}, $this->layout);
中找不到标签,则$this->data
保持不变。
您可以使用?? $matches[0]
:
preg_replace_callback
演示:preg_replace_callback
Shorter PHP 7.4版本:
$result = preg_replace_callback('/\[\[(?<tag>.*?)]]/', function ($matches) {
return $this->data[$matches['tag']] ?? $matches[0];
}, $this->layout);
https://3v4l.org/I9Vvh编辑(@Barmar提供)-这基本上是相同的答案,只是在PHP 7.4语法有用的情况下保留它。