6

Possible Duplicate:
replace multiple placeholders with php?

I've got a .txt-file working as a template. I've made several placeholders like {{NAME}} and I'd like to replace these with variables. What is the most efficient way to do this? Keep in mind that I have around 10 of these placeholders in my template.

Is there no better way than str_replace?

Community
  • 1
  • 1
OptimusCrime
  • 14,662
  • 13
  • 58
  • 96
  • You can always create your own function which wraps around `str_replace` and maybe takes an array as input. That's what I would do. – Felix Kling Nov 02 '11 at 13:01
  • 2
    Can you explain the *actual* issue with `str_replace()`? – Phil Nov 02 '11 at 13:02
  • You want to replace it with variables or with the content of variables? And how is it ugly -- compared to what? Maybe you should share some code, how you do things at the moment ... – aurora Nov 02 '11 at 13:03
  • 1
    @Felix Kling `str_replace` actualy can take an array as input since 4.3.3 – k102 Nov 02 '11 at 13:06
  • I would like to replace it with the content of the variables. What I am doing now is loading the content using file_get_contents, and I have a array with the placeholders as keys and the set the values as value. How does for example template-engines do this? The same way? – OptimusCrime Nov 02 '11 at 13:07
  • What are you using these text files for? Is it a one-time thing, or are you integrating this into a larger application (e.g., email templates)? You might want to consider a templating engine such as [Smarty](http://www.smarty.net/) or [Twig](http://twig.sensiolabs.org/). –  Nov 02 '11 at 13:08
  • `str_replace` with arrays is applying replaces on already done replacements, which can cause issues. See a related question: [Does PHP str_replace have a greater than 13 character limit?](http://stackoverflow.com/q/7771658/367456). – hakre Nov 02 '11 at 13:08
  • @k102: Right, somehow I had `sprintf` in mind.... – Felix Kling Nov 02 '11 at 13:09

3 Answers3

17

What about strtr

$trans = array(
    '{{NAME}}' => $name, 
    "{{AGE}}"   => $age,
    ......
);
echo strtr($text, $trans);
xdazz
  • 158,678
  • 38
  • 247
  • 274
8

str_replace is not only ugly, but also sluggish if you need to replace ten variables (does a binary search and starts from the beginning for each alternative).

Rather use a preg_replace_callback, either listing all 10 variables at once, or using a late-lookup:

$src = preg_replace_callback('/\{\{(\w+)}}/', 'replace_vars', $src);
                     # or (NAME|THING|FOO|BAR|FIVE|SIX|SVN|EGT|NNE|TEN)

function replace_vars($match) {
    list ($_, $name) = $match;
    if (isset($this->vars[$name])) return $this->vars[$name];
}
ABu
  • 10,423
  • 6
  • 52
  • 103
mario
  • 144,265
  • 20
  • 237
  • 291
  • Ehm... using regular expressions instead of exact search? Doesn't seem like a good way to boost performance... – Ivan Nov 02 '11 at 13:10
  • 5
    Well, when boosting performance you should look at actual benchmarks, not make presumptions ;) - PCRE is very highly optimized to search for alternatives. str_replace uses a loop internally. 'Regex is always slower' is the most misguided meme around here. No wait, second most. – mario Nov 02 '11 at 13:12
  • Thanks! This was a really good example. I was thinking about performance when I did not want to use str_replace. I've heard it's very slow. I'll try your solution. – OptimusCrime Nov 02 '11 at 13:46
0

What so ugly about str_replace()?

function replace_vars($string)
{
    $vars = array('NAME'=>'Name', 'VAR2'=>'Value 2', 'VAR3'=>'Value 3');

    $names = array();
    foreach($vars as $name=>$var) {
        $names[] = '{{'.$name.'}';
    }

    return str_replace($names, $vars, $string);
}

or

function replace_vars($string)
{
    $vars = array('{{NAME}}'=>'Name', '{{VAR2}}'=>'Value 2', '{{VAR3}}'=>'Value 3');

    return str_replace(array_keys($vars), $vars, $string);
}
PeeHaa
  • 71,436
  • 58
  • 190
  • 262
  • Try with: `$vars = array('{{NAME}}'=>'{{VAR2}}', '{{VAR2}}'=>'Value 2');` – hakre Nov 02 '11 at 13:10
  • 1
    Isn't that the reason we use the `{{...}}` format. To prevent it being a value somewhere by accident? – PeeHaa Nov 02 '11 at 13:20
  • 1
    Well, with the code example, you would replace substitutes again, rendering that reason meaningless, you can not distinguish the replacement state (A := to be replaced; B := replaced). The `{{...}}` are given for state A, not B. The code applies them (partially) to state B as well, which could be seen as a flaw resulting in unexpected and even erroneous behavior. My comment was made as a safeguard. It might work in 99.9% of all cases, but what about the rest? – hakre Nov 02 '11 at 14:30