Есть ли способ передать другой параметр в функцию обратного вызова preg_replace_callback? - PullRequest
9 голосов
/ 21 апреля 2010

мммм, ребята, я действительно надеюсь, что мой английский достаточно хорош, чтобы объяснить, что мне нужно.

Давайте возьмем пример (это просто пример!) Кода:

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

Итак, руководство php говорит, что для использования метода класса в качестве обратного вызова в preg_replace_callback() метод должен быть абстрактным.

Мне нужно передать экземпляр ранее инициализированнойобъект (в примере, экземпляр класса Something) в функции обратного вызова.

Я пытался использовать call_user_func(), но не работает (так как я пропускаю matches параметр).

Есть ли способ сделать это, или я должен разделить процесс (выполнение до preg_match_all, для каждого совпадения получить значение замены, а затем простой preg_replace)?

редактировать: в качестве примечания, перед тем как ответить Том Хей, я использовал этот обходной путь (в данном примере это метод замены):

$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;
}

Надежда может кому-то помочь.

Ответы [ 3 ]

13 голосов
/ 21 апреля 2010

Трудно передать аргументы обратным вызовам, но вместо этого:

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

Вы можете сделать Bar() не статичным и использовать это:

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

Тогда функция обратного вызова сможет увидеть $this

См. 'Обратный вызов' в Псевдотипы и переменные

Также в PHP> = 5.3 вы можете использовать анонимные функции / замыкания для передачи других данных в функции обратного вызова.

12 голосов

Я застрял при попытке передать аргумент (дополнительный параметр) в обратный вызов с методами create_function () и call_user_function ().

Это для справки:

<?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).
0 голосов
/ 12 апреля 2012

да, я использую что-то вроде этого для установки и сброса изменяемой переменной, чтобы она была доступна для функции обратного вызова, и вам не нужен более новый php для этого:

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

тогда в функции обратного вызова $ this -> _ current_key доступно:

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

    //and still remove found string
    return '';
}
...