0

I am trying to replace content of some tags in included files with content from other files:

$view = preg_replace('/{include ([[:alnum:]\.-]+)}/', ((file_exists('template/$1.html')) ? 'OK $1' : 'KO $1'), file_get_contents('myTemplateFile.tpl'));

All the {include file.ext} references I got in myTemplateFile.tpl are replaced with KO file.ext instead of OK file.ext.

However, if I hardcode file_exists('template/file.ext'), then the right string is displayed.

It appears to me the back-reference is not correctly resolved inside the file_exists call.

What am I doing wrong?

Bernard Rosset
  • 4,523
  • 6
  • 27
  • 29

2 Answers2

1
$view = preg_replace(
    '/{include ([[:alnum:]\.-]+)}/', 
    ((file_exists('template/$1.html')) ? 'OK $1' : 'KO $1'), 
    file_get_contents('myTemplateFile.tpl')
);

The above code is executed as follows:

$contents = file_get_contents('myTemplateFile.tpl');

if ((file_exists('template/$1.html')) {
    $result = preg_replace('/{include ([[:alnum:]\.-]+)}/', 'OK $1', $contents);
} else {
    $result = preg_replace('/{include ([[:alnum:]\.-]+)}/', 'KO $1', $contents);
}

As you can see, the file_exists() call is performed before the preg_replace() statement. It is checking for the existence of the file "template/$1.html", where $1 is a literal string which has no special meaning. That file doesn't exist, and the else block (originally 'KO $1') will always get executed.

In short, you can't use the backreferences from preg_replace() function outside the preg_replace() function. The solution is preg_replace_callback():

preg_replace_callback(
    '/{include ([[:alnum:]\.-]+)}/',
    function ($m) {
        return file_exists('template/'.$m[1].'html') ? 'OK '.$m[1]: 'KO '.$m[1];
    },
    file_get_contents('myTemplateFile.tpl')
);

See also:

Community
  • 1
  • 1
Amal Murali
  • 75,622
  • 18
  • 128
  • 150
  • Thanks for your help, although you are second... Gave a +1 anyway as a reward ;o) – Bernard Rosset Feb 14 '14 at 19:54
  • Well my bad. However, the other answer explains step-by-step where the problem comes from, having helped me to remember how recursive stuff are being processed. :oP I hope you won't have hard feelings towards me about still being second... ;o) – Bernard Rosset Feb 14 '14 at 20:15
1
preg_replace('/{include ([[:alnum:]\.-]+)}/', ((file_exists('template/$1.html')) ? 'OK $1' : 'KO $1'), file_get_contents('myTemplateFile.tpl'))

This first executes file_exists('template/$1.html'), then passes OK $1 or KO $1 (likely the latter) to preg_replace, which then replaces all occurrences.

You'll have to use a callback to make this work, not call file_exists as argument:

preg_replace_callback(
    '/{include ([[:alnum:]\.-]+)}/',
    function (array $m) {
        return file_exists("template/$m[1].html") ? "OK $m[1]" : "KO $m[1]";
    },
    file_get_contents('myTemplateFile.tpl')
)
deceze
  • 510,633
  • 85
  • 743
  • 889
  • Thanks! I did not pay attention to the way recursive calls were resolved... Of course file_exists is called first before preg_replace is even being evaluated! – Bernard Rosset Feb 14 '14 at 19:53