PHP中preg_replace_callback函数的use子句中的变量问题

q9rjltbz  于 2023-06-20  发布在  PHP
关注(0)|答案(2)|浏览(132)

我在回调函数中遇到了奇怪的行为。下面是在创建替换Map时将字符串的每个字母替换为序列号的代码。

$i = 2;
$map = [];
$token = preg_replace_callback(
  '~\w~',
  function($matches) use($map, $i) {
    $i += 1;
    $map[$i] = $matches[0];
    print "$i ";
    return $i;
  },
  '$token'
);
print_r($map);
print "\n$token";

奇怪的是它能打印

3 3 3 3 3 Array
(
)

$33333

即$i值被采用,但它正在改变,而不是在下一个回调调用中使用。这是怎么回事如何修复它?
https://onlinephp.io/c/a4b1c0下方的沙盒

nfs0ujit

nfs0ujit1#

通过引用传递use参数,如下所示:

$token = preg_replace_callback('~\w~', function ($matches) use (&$map, &$i) {
        $i += 1;
        $map[$i] = $matches[0];
        print "$i ";
        
        return $i;
    }, '$token');

生产:

3 4 5 6 7 Array
(
[3] => t
[4] => o
[5] => k
[6] => e
[7] => n
)

$34567

您必须澄清您的问题,以确定这是否是除了明显的价值与参考问题之外所期望的。

sulc1iza

sulc1iza2#

PHP中的变量捕获默认是 * 仅通过值 * -当创建闭包时,检查use列表中每个变量的当前值,并将其分配给闭包中同名的局部变量。在闭包内部赋值给局部变量并不会写回最初捕获的变量,并且每次执行闭包时,捕获的变量都以其最初捕获的值开始。
这与其他一些语言不同,如JavaScript,其中闭包携带对其捕获的变量的可写引用。按值捕获通常更容易理解,例如,如果你想在循环中创建一个闭包列表:

$callbacks = [];
foreach ( [1,3,5,7,9] as $number ) {
    $callbacks[] = function() use ($number) { return $number; };
}

如果$number是通过引用捕获的,那么所有五个闭包最终都是相同的,都引用同一个变量;因为它是按值捕获的,所以会得到五个不同的闭包,每个闭包都有不同的$number值。
如果你需要引用,你可以在use列表中使用&修饰符:

function($matches) use(&$map, &$i) {
   // ...
}

现在,闭包内部的本地名称$map与外部的名称$map引用 * 相同的变量 *-对其中一个的任何修改都将在另一个中可见。
这类似于$myMap = $yourMap(赋值)和$myMap =& $yourMap(链接两个变量作为引用)之间的区别。
(Note在上述所有情况下,对象的“值”是指向可变对象的指针-因此,如果$map是一个对象而不是数组,则调用$map->setSomething(42)将修改闭包内外可见的同一对象。这与通过引用捕获或赋值不同。)

相关问题