PHP array_walk 回调函数中变量引用传递的最佳实践

在 PHP 中使用 array_walk 时,如果要通过回调函数更改外部变量,则必须执行此操作。

Core是array_walk的第三个参数,默认按值传递。
但是,如果将该参数作为回调函数的引用传递(在形式参数前面添加 &),则可以更改外部变量。

在回调函数中,将要改变的参数声明为引用参数。
例如: php 函数collectKeys($value, $key, &$targetArray) { $targetArray[] = $key; }
这里&是$$targetArray前面的要点。

然后在调用array_walk时,直接传递变量,不加 & : php $inventory = ['苹果' => [...], '橙子' => [...]]; $水果=[]; array_walk($inventory, 'collectKeys', $fruits);
如果使用匿名函数,则必须使用 using 关键字将变量视为引用: php $fruits_anon = []; array_walk($inventory, 函数($value, $key) use (&$fruits_anon) { $fruits_anon[] = $key; });
看,&是在回调函数中使用的,但是在调用时却没有使用。

例如,收集数组的键: php $inventory = ['苹果' => [...], '橙子' => [...]]; $水果=[]; 函数collectKeys($value, $key, &$targetArray) { $targetArray[] = $key; } array_walk($inventory, 'collectkeys', $fruits); print_r($水果); // array([0] => apples, [1 ] => Oranges)
对于第二个示例,修改元素并记录: php $数字 = [1 , 2 , 3 ]; $操作日志=[]; 函数 processAndLog(&$item, $key, &$$logArray) { $项目= 2 ; $logArray[] = "已处理键为'$key'的元素,新值为$item"; } array_walk($number, 'processAndLog', $operationLog); print_r($数字); // 数组([0] => 2 , [1 ] => 4 , [2 ] => 6 ) print_r($操作日志); // Array ([0] => 处理了键为 '0' 的元素,新值为 2 , [1 ] => 处理了键为 '1 ' 的元素done,新值为4 ,[2 ] =>处理了key为'2 '的元素,新值为6 )
注意,如果调用array_walk时直接添加&,会出现语法错误: php array_walk($inventory, 'collectKeys', &$fruits); // error
回调函数中没有&,所以无法改出: php function FruitType($value, $key, $fruit) { // 没有其他 $fruit[] = $key; } array_walk($inventory, 'FruitTypes', $Fruits); // $fruits external 还是空的
记住,回调函数的参数顺序是$value,$key,&$userdata,不要搞乱。

与array_map不同,array_walk可以修改原始数组或聚合数据。
array_map 生成一个新数组而不触及原始数组。

通过引用传递参数比较省事,因为不需要复制数据,但在小型数组上性能差异并不大。
还是要看代码能不能看懂。

回调函数可以是全局函数、匿名函数、静态方法或对象方法。
匿名函数必须使用 (&$var) 来表示引用。

简单来说,回调函数中参数前面加&,调用时直接传递变量,匿名函数使用(&$var)。
这样你就可以改变外部变量。

php如何使用全局变量

老实说,我一直觉得在 PHP 中处理全局变量很有趣。
想想看,变量可以在脚本中的任何地方直接使用。
这确实很灵活,但可能会意外地变得混乱。

我第一次接一个老项目的时候就经历过这个坑。
当时有一个计数器函数,我写了一个函数,但每次调用它时计数器都会重置。
经过检查,发现没有包含static关键字。
现在,我只能想:我应该对全局变量做些什么吗?这样,状态就可以在函数调用之间得以保留。

但是当我使用global关键字时,我必须提醒自己。
例如,我刚刚编写了一个日志函数,需要在每个函数中快速记录一些内容,我使用了全局变量。
结果后来团队重组的时候,有人改了变量名,到处报错,真是让人头疼。
坦率地说,过多依赖全局变量就像在代码中置入雷区。
你看不到它,但你不会善待别人踩到它。

至于$GLOBALS这个技巧,我个人认为很好用。
记得有一次,我在写CMS系统时,要根据不同的模块加载不同的配置。
这些配置名称都是动态的,使用 $GLOBALS 直接通过名称访问它们特别方便。
而且修改起来也很简单,只需 $GLOBALS['config_name'] = 'new_value';这一切都在一条线上完成。
当然,如果变量太多,数组就会显得眼花缭乱。

至于回引号技巧,我承认我自己在这方面没有做过很多场景。
我看文档的时候觉得挺高级的,但是在实际业务中用的不多。
确实,在函数中写 return &$var 可以直接修改全局变量的值,光是想想就有点兴奋。
但如果用得太多,你可能就无法理解了。
毕竟这是PHP中比较底层的操作。

其实我更推荐使用参数传递或者返回值来共享数据。
例如,如果一个函数需要修改全局状态,它被设计为返回一个新值,调用者检索该新值,然后将其分配给全局变量。
这样耦合度低且易于更改。
你看,我去年重构一个系统的时候就是这么做的。
当我稍后想添加单元测试时,代码就清晰多了。

但是话虽如此,每种方法都有其用处。
在简单的场景中,global确实更直接;当动态变量名较多时,$GLOBALS很方便;如果您确实想执行高级操作,返回引用也可以。
关键是知道什么时候使用它,什么时候不使用它。
这就像开车一样。
踩油门的感觉很好,但随时都可能出问题。