Is there a way to pass another parameter in the preg_replace_callback callback function?
Asked Answered
T

3

9

mmmh guys, i really hope my english is good enaught to explain what i need.

Lets take this example (that is just an example!) of code:

class Something(){
    public function Lower($string){
        return strtolower($string);
    }
}
class Foo{
    public $something;
    public $reg;
    public $string;
    public function __construct($reg, $string, $something){
        $this->something = $something;
        $this->reg = $reg;
        $this->string = $string;
    }
    public function Replace(){
        return preg_replace_callback($this->reg, 'Foo::Bar', $this->string);
    }
    public static function Bar($matches){
        /*
        * [...]
        * do something with $matches and create the $output variable
        * [...]
        */

        /*
        * I know is really useless in this example, but i need to have an istance to an object here
        * (in this example, the Something object, but can be something else!)
        */
        return $this->something->Lower($output);
    }
}
$s = new Something();
$foo = new Foo($myregexp, $mystring, $s);
$content = $foo->Replace();

So, the php manual say that to use a class method as callback in preg_replace_callback(), the method must be abstract.

I need to pass an instance of a previuosly initialized object (in the example, an instance of the Something class) at the callback function.

I tryed to use call_user_func(), but doesnt work (becose in this way i miss the matches parameter).

Is there a way to do that, or have i to separate the process (doing before preg_match_all, for each match retrieve the replace value, and then a simple preg_replace)?

edit: as a side-note, before the tom haigh answer, i used this work-around (in the example, this is the Replace method):

$has_dynamic = preg_match_all($this->reg, $this->string, $dynamic);
if($has_dynamic){
    /*
    * The 'usefull' subset of my regexp is the third, so $dynamic[2]
    */
    foreach($dynamic[2] AS $key => $value){
        $dynamic['replaces'][$key] = $this->Bar($value);
    }
    /*
    * ..but i need to replace the complete subset, so $dynamic[0]
    */
    return str_replace($dynamic[0], $dynamic['replaces'], $this->string);
}else{
    return $this->string;
}

Hope can help someone.

Tavia answered 21/4, 2010 at 7:19 Comment(0)
B
14

It is hard to pass arguments to callbacks, but instead of this:

return preg_replace_callback($this->reg, 'Foo::Bar', $this->string);

You could make Bar() not static, and use this:

return preg_replace_callback($this->reg, array($this, 'Bar'), $this->string);

Then the callback function will be able to see $this

See 'callback' in Pseudo-types and variables

Also in PHP >=5.3 you could use anonymous functions/closures to pass other data to callback functions.

Bushranger answered 21/4, 2010 at 8:4 Comment(1)
This works! I thought that the class method have to be static, dont remember where i did read it.. maybe i didnt at all and I messy with some sentences. ThanksTavia
S
13

I got stuck while trying to pass an argument (extra parameter) to a callback with the create_function() and call_user_function() methods.

This is for reference:

<?php
$pattern = "/([MmT][a-z]*)/";
$string = "Mary is a naughty girl because she took all my animals.";
$kill = "Mary";

echo preg_replace_callback($pattern, function($ma) use ($kill) {

    foreach ($ma as $m){
        if ($m == $kill){
            return "Jenny";
        }
        return "($m)";
    }
}, $string);

echo "\n";
?>

$ php preg_replace_callback.php 
Jenny is a naughty girl because she took all (my) ani(mals).
Selfexpression answered 24/6, 2011 at 22:42 Comment(3)
should note the use keyword was added in PHP 5.4. most servers are still running 5.3 :(Parable
@Mark the use keywords is added in PHP5.3Interblend
THIS is the solution. Thanks! Really needed to know this.Macro
G
0

yes I use something like this to set and unset a changing variable so that it is available to the callback function and you don't need the newer php to do it:

foreach ($array as $key) {
    $this->_current_key = $key;
    preg_replace_callback($regex, array($this, '_callback'), $content);
    unset($this->_current_key);
}

then in the callback function $this->_current_key is available:

function _callback ($match) {    
    //use the key to do something
    new_array[$key] = $match[0];

    //and still remove found string
    return '';
}
Glassman answered 11/4, 2012 at 23:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.