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);
2

3 Answers 3

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
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, this is exactly what I was hoping was possible Appreciate the sample, it's very clear and I was able to adapt it.
Whoever reads this: you might want to use the keyword use instead of this relatively complex approach (see this answer by @Mark Baker for more info)
The answer in the comment above from @TheSexiestManinJamaica offers a much better and simpler solution to this problem than adding new classes etc.
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.
24
$pattern = '';
$foo = 'some text';

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

}, $content);

Comments

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.

1 Comment

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.