Lorenz Meyer Lorenz Meyer - 5 months ago 10
PHP Question

How to expand variables in a string

Problem



I'd like to expand variables in a string in the same manner that variable in a double quoted string get expanded.

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


$string
should become
'<p>It took 40 s</>';


I see a obvious solution like this:

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


But I really don't like it, because eval() is insecure. Is there any other way to do this ?

Context



I'm building a simple templateing engine, that's where I need this.

Example Template (view_file.php)

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


Template rendering (simplified code):

$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;
}


The expansion of the variables in the template simplifies it's syntax. Without it, the above example template would be:

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


Do you think this approach is good ? Or should I look in another direction ?

Edit



Finally I understand that there is no simple solution due to flexible way PHP expands variables (even
${$var}->member[0]
would be valid.

So there are only two options:


  1. Adopt an existing full fledged templating system

  2. Stick with something very basic that essentially is limited to including the view files via
    include
    .


Answer

I would rather suggest using some existing template engines, like for example Smarty, but if you really want to do it by yourself you can use the simple regular expression to match all variables constructed with for example letters and numbers and then replace them with correct variables:

<?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;

?>

prints

hello World, what is the matter? I like World!

Comments