× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

array_walk 等 PHP 内置函数替换 [过期]

在4.4.4后不再进行函数替换,而是使用底层上下文切换完美解决了该问题,100%兼容,但仍推荐开发者使用foreach而不是array_walk(foreach通常具有更好性能和底层实现)

4.4版本中,底层替换了array_walkarray_walk_recursive函数。主要原因是这些函数在PHP的底层实现中使用了C/C++全局变量,导致协程切换过程中会出现内存越界。在Swoole中使用了PHP代码实现的函数替换了底层的内置函数。

差异

使用array_walk遍历对象属性时可能与内置函数的行为不一致。

  • 协程 array_walk 不支持传入 Object 类型

内置函数

class A
{
    public $a = 1;
    public $b = 2;
    public $c = '3';
    private $d = 'hello';
}

$o = new A;

array_walk($o, function ($v, $k) {
    echo $k, " ->", $v, PHP_EOL;
});

上述代码中,未使用协程,仍然使用内置函数。输出结果是:

php array_walk.php
a ->1
b ->2
c ->3
 A d ->hello

可以读取到私有变量。

协程替换函数

Co\Run(function () {
    $o = new A;
    array_walk($o, function ($v, $k) {
        echo $k, " ->", $v, PHP_EOL;
    });
});

在协程中使用array_walk操作对象,将直接抛出致命错误。

PHP Fatal error:  Uncaught TypeError: Argument 1 passed to swoole_array_walk() must be of the type array, object given in @swoole-src/library/std/array.php:2
Stack trace:
#0 [internal function]: swoole_array_walk(Object(A), Object(Closure))
#1 /mnt/d/workspace/code/array_walk.php(15): array_walk(Object(A), Object(Closure))
#2 {main}
  thrown in @swoole-src/library/std/array.php on line 2