一种更好的搜索和替换模板的方法


A better way to do this search and replace for a template

我目前做搜索和替换一个网页模板,像这样:

$template = <<<TEMP
<html>
<head>
<title>[{pageTitle}]</title>
</head>
[{menuA}]
[{menuB}]
[{bodyContent}]
</html>
<<<TEMP;

以上内容放在一个单独的文件中

然后,我做:

$template = str_replace("[{pageTitle}]",$pageTitle,$template);
$template = str_replace("[{menuA}]",$menuA,$template);
$template = str_replace("[{menuB}]",$menuB,$template);
$template = str_replace("[{bodyContent}]",$bodyContent,$template);
//Some 10 more similar to the above go here.
echo $template;

问题是,总共有15个和上面的一样。

是否有更好/更干净/更专业的方法来做到这一点(要么搜索和替换,要么以不同的方式做整个事情)。

是的,你可以定义一个包含你想要替换的东西的数组和另一个包含要替换的东西的数组。

$array1 = array("[{pageTitle}]", "[{menuA}]");
$array2 = array($pageTitle, $menuA);
$template = str_replace($array1 , $array2 , $template);

通过修改ljubicicica的答案。你可以用变量和值创建关联数组,然后替换它们:

$array=array(
        'pageTitle'=>$pageTitle,
        'menuA'=> $menuA,
        );
$addBrackets = function($a)
{
    return '[{'.$a.'}]';
};
$array1 = array_keys($array);
$array1 = array_map($addBrackets,$array1);
$array2 = array_values($array);
$template = str_replace($array1 , $array2 , $template);

不要重新发明轮子,使用现有的模板引擎。我建议用树枝,因为它既简单又快捷!

最好的方法是使用现有的库,如Smarty或Twig。

如果你想滚动你自己的模板解决方案,你可以使用正则表达式:

// Just an example array
$values = array('pageTitle' => 'foo', 'menuA' => 'bar');
$offset = 0;
while(preg_match('/'['{([a-zA-Z]+)']'}/', $template, $matches, 
  PREG_OFFSET_CAPTURE, $offset)) {
    $varname = $matches[0][3];
    $value = isset($values[$varname]) ? $values[$varname] : "Not found!";
    $template = str_replace('[{'.$varname.'}]', $value, $template);
    $offset = $matches[1];
}

如果你不喜欢关联数组,你可以这样做:

$value = isset($$varname)? $$varname : "Not found";

但是我不建议这样做,因为它可能会暴露你不想暴露的变量

使用正则表达式怎么样?如下所示:

   $matches = array();
    preg_match_all("/'['{.*?'}']/", $template, $matches);
    foreach ($matches[0] as $match){
    // this will replace the '[{','}]' braces as we don't want these in our file name
    $var = str_replace("[{", "", $match);
    $var = str_replace("}]", "", $var);
    // this should pull in the file name and continue the output
    $template = str_replace($match, $$var, $template);
    }

我还没有测试过,但这样你就不必知道你需要替换什么了?它会取代你的[{text}]标签$text为例?

我发现像这样的东西实际上是有效的:

    $foo = 'bar';
    $baz = 'foo';
    $test = 'Test [{foo}] and [{baz}]';
    $test1 = preg_replace("/'[{(.*?)}']/e", "$$1", $test);
    $test2 = preg_replace_callback("/'[{(.*?)}']/", function($v) use($foo, $baz)
            {
                return ${$v[1]};
            }, $test);
    var_dump($test1); //string 'Test bar and foo' (length=16)
    var_dump($test2); //string 'Test bar and foo' (length=16)

所以在你的例子中:

$template= preg_replace("/'[{(.*?)}']/e", "$$1", $template);
编辑:

您还可以检查变量是否像这样设置:

    $foo = 'bar';
    $baz = 'foo';
    $test = 'Test [{foo}] and [{baz}] or [{ble}]';
    $test1 = preg_replace("/'[{(.*?)}']/e", "isset($$1) ? $$1 : '$$1';", $test);
    var_dump($test1); //string 'Test bar and foo or $ble' (length=24)