如何在字符串中扩展变量

时间:2013-09-04 16:38:22

标签: php string

问题

我希望扩展字符串中的变量,方法与双引号字符串中的变量扩展相同。

$string = '<p>It took $replace s</>';
$replace = 40;
expression_i_look_for;

$string应该成为'<p>It took 40 s</>';

我看到一个明显的解决方案:

$string = str_replace('"', '\"', $string);
eval('$string = "$string";');

但我真的不喜欢它,因为eval()是不安全的。还有其他办法吗?

上下文

我正在构建一个简单的模板引擎,这就是我需要的地方。

示例模板(view_file.php)

<h1>$title</h1>
<p>$content</p>

模板渲染(简化代码):

$params = array('title' => ...);

function render($view_file, $params)
    extract($params)
    ob_start();
    include($view_file);
    $text = ob_get_contents();
    ob_end_clean();
    expression_i_look_for; // this will expand the variables in the template
    return $text;
}

模板中变量的扩展简化了它的语法。没有它,上面的示例模板将是:

<h1><?php echo $title;?></h1>
<p><?php echo $content;?></p>

你觉得这种做法好吗?或者我应该向另一个方向看?

修改

最后我明白,由于PHP扩展变量的灵活方式,没有简单的解决方案(即使${$var}->member[0]也是有效的。

所以只有两个选择:

  1. 采用现有的完整模板系统
  2. 坚持一些非常基本的东西,基本上只限于通过include包含视图文件。

7 个答案:

答案 0 :(得分:4)

我宁愿建议使用一些现有的模板引擎,例如Smarty,但是如果你真的想自己做,你可以使用简单的正则表达式来匹配用例如字母和数字构造的所有变量然后替换它们正确的变量:

<?php

$text = 'hello $world, what is the $matter? I like $world!';

preg_match_all('/\$([a-zA-Z0-9]+)/',
    $text,
    $out, PREG_PATTERN_ORDER);

$world = 'World';
$matter = 'matter';

foreach(array_unique($out[1]) as $variable){
    $text=str_replace('$'.$variable, $$variable, $text);
}

echo $text;

?>

打印

  你好世界,怎么回事?我喜欢世界!

答案 1 :(得分:1)

你想要这样的东西吗?

$replace = 40;
$string = '<p>It took {$replace}s</p>';

答案 2 :(得分:1)

解析

解析字符串查找$后跟有效变量名称(即\[a-zA-Z_\x7f-\xff\]\[a-zA-Z0-9_\x7f-\xff\]*

Variable²

使用variable variables syntax(即$$var表示法。)

答案 3 :(得分:0)

你想这样做吗?

templater.php:

<?php

$first = "first";
$second = "second";
$third = "third";

include('template.php');

的template.php:

<?php

echo 'The '.$first.', '.$second.', and '.$third.' variables in a string!';

运行templater.php时,生成:

"The first, second, and third variables in a string!"

答案 4 :(得分:0)

而不是使用单引号

$string = '<p>It took $replace s</>';
$replace = 40;

使用双引号

$replace = 40;
$string = "<p>It took $replace s</>";

但是,为了便于阅读并使您能够删除$ replace和s之间的空间我将使用:

$replace = 40;
string = '<p>It took ' . $replace . 's</>';

答案 5 :(得分:0)

正确的方法可能是将您的文档解析为树,识别您的解析器标记(因为您正在管理自己的解析器,如果您不希望它们,则不必遵循php约定)然后添加当机会出现时,你的值来自关联数组或其他数据结构。

这是一个更复杂的解决方案,但是当你意识到你希望能够使用基于标准显示选项的某种循环结构提前显示长度未知的列表时,会更容易。从长远来看,您将找不到许多严重的模板系统,这些系统没有将文档解析为某种内存树,可以插入占位符,然后根据需要构建文档。这也为缓存提供了许多机会。另外,如果你不怕递归,你可以很简单地对它进行大量的操作。

然而,这不是一个不常见的问题需要解决,正如我在这个问题上所评论的那样,几乎可以保证提供所需的大部分功能的库和扩展。除非这对您来说是一个纯粹的学术过程,否则我会找到一些现有的解决方案,或者使用其中一个解决方案,或者对其工作原理有充分的了解,这样您就有了适应自己解决方案的起点。

答案 6 :(得分:0)

这是我从Lejlot的回答中摘录的片段。我测试了它,它工作正常。

function resolve_vars_in_str( $input )
{
    preg_match_all('/\$([a-zA-Z0-9]+)/', $input, $out, PREG_PATTERN_ORDER);
    foreach(array_unique($out[1]) as $variable) $input=str_replace('$'.$variable, $GLOBALS["$variable"], $input);
    return $input ;
}