21

I've been researching similar questions, but I'm still a bit unclear if it's possible and/or best way to pass additional arguments in preg_replace_callback using PHP 5.2.6

In this case I'm also looking to pass the $key from the foreach loop along to the if_replace function.

public function output() {
if (!file_exists($this->file)) {
    return "Error loading template file ($this->file).<br />";
}
$output = file_get_contents($this->file);

foreach ($this->values as $key => $value) {
    $tagToReplace = "[@$key]";
    $output = str_replace($tagToReplace, $value, $output);
    $dynamic = preg_quote($key);
    $pattern = '%\[if @'.$dynamic.'\](.*?)\[/if\]%'; // produces: %\[if @username\](.*?)\[/if\]%
    $output = preg_replace_callback($pattern, array($this, 'if_replace'), $output);
}

return $output;
}



public function if_replace($matches) {

    $matches[0] = preg_replace("%\[if @username\]%", "", $matches[0]);
    $matches[0] = preg_replace("%\[/if]%", "", $matches[0]);
    return $matches[0];
}

Wondering if something like this would work:

class Caller {

public function if_replace($matches) {

    $matches[0] = preg_replace("%\[if @username\]%", "", $matches[0]);
    $matches[0] = preg_replace("%\[/if]%", "", $matches[0]);
    return $matches[0];
}

}

$instance = new Caller;

$output = preg_replace_callback($pattern, array($instance, 'if_replace'), $output);
hakre
  • 193,403
  • 52
  • 435
  • 836
jsuissa
  • 1,754
  • 6
  • 30
  • 64
  • Acallback function is a closure, you can pass extra arguments via use, please check answer at http://stackoverflow.com/questions/16445991/how-do-i-access-a-variable-inside-of-preg-replace-callback – Tester Jun 04 '14 at 19:12
  • Related: [Callback function using variables calculated outside of it](https://stackoverflow.com/q/4588714/2943403) – mickmackusa Mar 25 '23 at 07:04

3 Answers3

46

Before PHP 5.3

You can use helper class:

class MyCallback {
    private $key;

    function __construct($key) {
        $this->key = $key;
    }

    public function callback($matches) {
        return sprintf('%s-%s', reset($matches), $this->key);
    }
}

$output = 'abca';
$pattern = '/a/';
$key = 'key';
$callback = new MyCallback($key);
$output = preg_replace_callback($pattern, array($callback, 'callback'), $output);
print $output; //prints: a-keybca-key

Since PHP 5.3

You can use anonymous function:

$output = 'abca';
$pattern = '/a/';
$key = 'key';
$output = preg_replace_callback(
    $pattern, 
    function ($matches) use($key) {
        return sprintf('%s-%s', reset($matches), $key);
    },
    $output
);
print $output; //prints: a-keybca-key

Since PHP 7.4

You can use short closure (aka arrow function):

$output = 'abca';
$pattern = '/a/';
$key = 'key';
$output = preg_replace_callback(
    $pattern, 
    fn ($matches) => sprintf('%s-%s', reset($matches), $key),
    $output
);
print $output; //prints: a-keybca-key
Furgas
  • 2,729
  • 1
  • 18
  • 27
  • Thanks, this is exactly what I was hoping was possible Appreciate the sample, it's very clear and I was able to adapt it. – jsuissa Mar 04 '12 at 00:19
  • 1
    Whoever reads this: you might want to use the keyword `use` instead of this relatively complex approach (see [this answer by @Mark Baker](http://stackoverflow.com/a/16446110/722036) for more info) – ᴍᴇʜᴏᴠ Jan 19 '16 at 21:19
  • The answer in the comment above from @TheSexiestManinJamaica offers a much better and simpler solution to this problem than adding new classes etc. – Chris Feb 07 '16 at 15:19
  • 1
    The question was for PHP 5.2.6, but I've updated the answer to include solution with anonymous functions introduced in PHP 5.3, as in @Bald answer. – Furgas Feb 08 '16 at 10:35
22
$pattern = '';
$foo = 'some text';

return preg_replace_callback($pattern, function($match) use($foo)
{
var_dump($foo);

}, $content);
Bald
  • 2,156
  • 3
  • 24
  • 33
2

Unfortunately you can't. In PHP 5.3 you could simply use a closure to have access to the variables you'd pass as parameters.

In your case there are two possible solutions: A clean and a dirty one.

The dirty one is storing the params in global variables so you can access them from inside the callback.

The clean one is creating a class where you pass the params e.g. via the constructor. Then you use array($instance, 'methodName') as the callback and simply access the params via $this->whatever inside your method.

ThiefMaster
  • 310,957
  • 84
  • 592
  • 636
  • Thanks that's got me going in the right direction. I updated the question based on your comment, I believe I understand what you're suggesting. – jsuissa Mar 03 '12 at 23:57