Gary Willoughby Gary Willoughby - 20 days ago 5
PHP Question

Using PHP how can I apply HTMLentities() to a backreference in a preg_replace() call?

At the minute I have:

$Text = preg_replace("/\[code\](.*?)\[\/code\]/s", "<mytag>\\1</mytag>", $Text);


How can I escape the backreference using
htmlentities()
?

Answer
$Text = "foo [code]bla<br>bla[/code] foo";

echo preg_replace_callback('/\[code\](.*?)\[\/code\]/s', 'wrap_code', $Text);

function wrap_code($matches) { 
  return '<mytag>'.htmlspecialchars($matches[1]).'</mytag>';
}

As seen in the preg_replace_callback() documentation, you can also create the callback function inline, via create_function() or as of PHP 5.3.0 even use an anonymous function.


The generic approach however would be along the lines of this:

$Text = "foo [code]bla<br>bla[/code] foo";

$re_bbcode = '/\[(code|b|whatever)\](.*?)\[\/\1\]/s';
echo preg_replace_callback($re_bbcode, 'wrap_code', $Text);

function wrap_code($matches) { 
  switch ($matches[1]) {
    case 'code': $tag = 'mytag'; break;
    case 'b'   : $tag = 'b';     break;
    default    : $tag = ''; 
  }
  if ($tag != '')
    return "<$tag>".htmlspecialchars($matches[2])."</$tag>";
  else
    return htmlspecialchars($matches[0]);
}

Also I guess (I have not measured) that this regex could be a bit faster, because the reluctant quantifier would not be invoked more often than necessary:

\[(code|b|whatever)\]([^\[]+|.*?)\[\/\1\]