Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg

PHP : Function Reference : Regular Expression Functions (Perl-Compatible) : preg_replace_callback


Perform a regular expression search and replace using a callback (PHP 4 >= 4.0.5, PHP 5)
mixed preg_replace_callback ( mixed pattern, callback callback, mixed subject [, int limit [, int &count]] )

Example 1723. preg_replace_callback() and create_function()

/* a unix-style command line filter to convert uppercase
* letters at the beginning of paragraphs to lowercase */
$fp = fopen("php://stdin", "r") or die("can't read stdin");
while (!
feof($fp)) {
$line = fgets($fp);
$line = preg_replace_callback(
// single quotes are essential here,
           // or alternative escape all $ as \$
'return strtolower($matches[0]);'

Example 1724. preg_replace_callback() example

// this text was used in 2002
// we want to get this up to date for 2003
$text = "April fools day is 04/01/2002\n";
$text.= "Last christmas was 12/24/2001\n";
// the callback function
function next_year($matches)
// as usual: $matches[0] is the complete match
 // $matches[1] the match for the first subpattern
 // enclosed in '(...)' and so on
return $matches[1].($matches[2]+1);


The above example will output:

April fools day is 04/01/2003
Last christmas was 12/24/2002

Example 1725. preg_replace_callback() using recursive structure to handle encapsulated BB code

= "plain [indent] deep [indent] deeper [/indent] deep [/indent] plain";


$regex = '#\[indent]((?:[^[]|\[(?!/?indent])|(?R))+)\[/indent]#';

   if (
is_array($input)) {
$input = '<div style="margin-left: 10px">'.$input[1].'</div>';

preg_replace_callback($regex, 'parseTagsRecursive', $input);

$output = parseTagsRecursive($input);


Code Examples / Notes » preg_replace_callback


You can use this function to display url address as a link or image based on suffix of the url.
Every string beginning with www or http(s):// will be displayed as an URL address.  But if the string ends with *.jpg or *.gif, it will be displayed as an image.
Please note: This function also verifies the size of the image. If is it more than 600x400, it changes it.
$pattern_html = "/\b((http(s?):\/\/)|(www\.))([\w\.]+)";
$pattern_html .= "([\#\,\/\~\?\&\=\;\%\-\w+\.]+)\b/i";
$text = preg_replace_callback($pattern_html,'Check_if_Image',$text);
function Check_if_Image($matches) {
$suffix = strtolower(substr($matches[0],-4));
if ( $suffix == '.jpg' or $suffix == '.gif') {
$dsn = 'http'.$matches[3].'://'.$matches[4].$matches[5];
if (list($width, $height, $type, $attr) = getimagesize("$dsn")) {
if ( ($width > 600) ) {
$koef = $width / 600;
$width = 600;
$height /= $koef;
if ( ($height > 400) ) {
$koef = $height / 400;
$height = 400;
$width /= $koef;
else {
$ret = "<img src=\"$dsn\"";
$ret .= "\" border=0 width=\"$width\" height=\"$height\">";
else {
$ret = '<a href="http'.$matches[3].'://'.$matches[4].$matches[5];
$ret .='" target="_blank">'.$matches[0].'</a>';
return ("$ret");


preg_replace_callback returns NULL when pcre.backtrack_limit is reached; this sometimes occurs faster then you might expect. No error is raised either; so don't forget to check for NULL yourself

sjungwirth domain matrix-consultants com

one way to 'pass' extra info other than just the matches and still use preg_replace_callback is to have your callback function be a class method, and just before you call preg_replace_callback, store the info in that class. I am using static methods/variables for my implementation; I'm not sure if its required.
class foo {
private static $bar;
public static function do_something($bar) {
self::$bar = $bar; // store bar

$input = $bar->get_somevar();
$pattern = "match me";
$output = preg_replace_callback($pattern, array('self', 'do_something_callback'), $input);

return $output;
private static function do_something_callback($matches) {
$bar = self::$bar; // retrieve bar

// do stuff like $bar->get_someothervar();

return $replacement;


it is much better on preformance and better practice to use the preg_replace_callback function instead of preg_replace with the e modifier.
function a($text){return($text);}
// 2.76 seconds to run 50000 times
// 0.97 seconds to run 50000 times


If you want to replace your matches with a unique calculation and you do not want to use:
1. preg_replace() and /e flag*
2. preg_replace_callback() and create_function()**
3. preg_replace_callback() and fill the namespace with an additional function
You can insert both call and solution within one function. Then, you may supply callback with the __FUNCTION__ predefined constant, and the function will separate its responsibilities itself by the type of the argument. Since preg_replace_callback() returns an array, this is easy. Quite useless example:
function debug($s)
   return preg_replace_callback('/{\?(cl|co|f|i|v)}/', __FUNCTION__, $s);
   'co'  =>'nstants',
   'f'   =>'unctions',
   'v'   =>'ars',
   'cl'  =>'asses',
   'i'   =>'nterfaces',
 ) as $p[1] => $p[2])
   if($p[1] === $s[1])
     $p[0] = in_array($p[1], array('cl', 'i')) ? 'declared' : 'defined';
     $f = vsprintf('get_%3$s_%2$s%1$s', $p); return var_export($f(), 1);
echo debug('Variables: {?v} Nothing: {?n} Interfaces: {?i}');
* I do not know whether it evokes eval() or not


If you want to do a date function in a template system you'll have to use the callback here.
function date_match ($matches)
  return date ($matches['2']);
$output = preg_replace_callback ('/({DATE=")(.{1,})("})/', 'date_match', $input);


If you want to be able to change variables of the class in the callback function, you have to use preg_replace_callback(pattern, array(&$this, 'method_name'), subject)
Probably very obvious, but it kept me busy for a while...


I thought I'd post this as I'd been using the function preg_replace_callback with NP within functions, but as soon as I re-wrote my script as a class, it all fell apart.
When debugging I ended up writing test code and this is what follows. It works as I'd expect, YMMV of course.
// v v over simplified
class foo
 function parse()
   $pattern = "/<a(.*?)href\s*=\s*['|\"|\s*](.*?)['|\"|>](.*?)>(.*?)<\/a>/i";
   $string = "<a class='whatever' href='' target='_blank'>foo</a>";
   print preg_replace_callback($pattern,array($this,'cb'),$string);
 function cb($matches)
   return "<a" . $matches[1] . "href='" . urlencode($matches[2]) . "'" . $matches[3] . ">" . $matches[4] . "</a>";
$bar = new foo();
output is
<a class='whatever' href='' target='_blank'>foo</a>


Add this snippet to your callback function to make sure you don't replace HTML code. Useful when searching / replacing / highlighting HTML. Change 90 to whatever threshold you need if you have extra extra long tags for some weird reason (lots of inline styles?)
function scanForTags($position, $maintext)
for($i = 1;$i < 90; $i++)

if($maintext{$position-$i} == "<" || $maintext{$position+$i} == ">")
return true;
if($maintext{$position-$i} == ">" || $maintext{$position+$i} == "<")
return false;
return false;


> sjungwirth domain matrix-consultants com
It may fail in nested condition if $bar needs to be changed.

Change Language

Follow Navioo On Twitter
Pattern Modifiers
Pattern Syntax
eXTReMe Tracker