传递引用不使用array_walk_recursive的其他参数,除非它是不推荐的调用时间传递引用

Mar*_*ker 6 php pass-by-reference

有一段时间了,我一直在使用"传统的"递归函数来展平多维数组,例如

$baseArray = array(array('alpha'),
                   array('beta','gamma'),
                   array(),
                   array(array('delta','epsilon'),
                         array('zeta',array('eta',
                                            'theta'
                                           ),
                              ),
                        ),
                   array('iota'),
                  );
Run Code Online (Sandbox Code Playgroud)

到一个简单的一维数组.

昨晚,我想我会看一下使用array_walk_recursive()来看看我是否可以让它更高效,更清洁.

我的第一次尝试不是很成功:

function flattenArray($arrayValue, $arrayKey, &$flatArray) {
    $flatArray[] = $arrayValue;
}


$flattenedArray = array();
array_walk_recursive($baseArray,'flattenArray',$flattenedArray);
Run Code Online (Sandbox Code Playgroud)

我认为它应该可行,但我得到的只是一系列错误:

Warning: Cannot use a scalar value as an array in C:\xampp\htdocs\arrayTest.php on line 16
Run Code Online (Sandbox Code Playgroud)

结果是:

array(0) { }
Run Code Online (Sandbox Code Playgroud)

我的flattenArray()函数中的类型提示给了我

Catchable fatal error: Argument 3 passed to flattenArray() must be an array, integer given in C:\xampp\htdocs\arrayTest.php on line 16
Run Code Online (Sandbox Code Playgroud)

使用闭包给出了相同的结果

我可以让它工作的唯一方法(无需使用全局或静态的flattenedArray)使用call-time pass-by-reference:

function flattenArray($arrayValue, $arrayKey, $flatArray) {
    $flatArray[] = $arrayValue;
}


$flattenedArray = array();
array_walk_recursive($baseArray,'flattenArray',&$flattenedArray);
Run Code Online (Sandbox Code Playgroud)

这会产生正确的结果

array(9) { [0]=> string(5) "alpha" [1]=> string(4) "beta" [2]=> string(5) "gamma" [3]=> string(5) "delta" [4]=> string(7) "epsilon" [5]=> string(4) "zeta" [6]=> string(3) "eta" [7]=> string(5) "theta" [8]=> string(4) "iota" }
Run Code Online (Sandbox Code Playgroud)

但是给了我一个意想不到的警告

Deprecated: Call-time pass-by-reference has been deprecated in C:\xampp\htdocs\arrayTest.php on line 22
Run Code Online (Sandbox Code Playgroud)

我知道PHP是一种古怪的语言,但这看起来有点极端.文档清楚地显示了array_walk_recursive的第一个参数是pass-by-reference,但似乎附加参数只能在调用时通过引用传递.奇怪的!

PHP版本是5.3.8

有关如何使用array_walk_recursive正确地展平我的数组,而不会被弃用的错误(除了提交错误报告)的任何建议.

编辑

PS

我知道我可以使用闭包绕过这个问题:

$flattenedArray = array();
array_walk_recursive($baseArray, function($arrayValue, $arrayKey) use(&$flattenedArray){ $flattenedArray[] = $arrayValue; } );
var_dump($flattenedArray);
Run Code Online (Sandbox Code Playgroud)

但由于这是当前允许与PHP 5.2.0一起使用的库所必需的,因此使用需要更高版本PHP的功能并不是一个实用的选择

Nik*_*kiC 6

以这种方式思考:你通过价值$flatArray进入.然后将通过引用你的函数进一步传递参数.但是当它按值传递时,引用将指向不同的值.array_walk_recursive array_walk_recursivearray_walk_recursive

我知道,这似乎是一个奇怪的限制,但是当你想到它时,它也是合乎逻辑的.

顺便说一下,我认为你不小心也发现了另一个问题,它实际上看起来像是严重的内存损坏(看看@ http://codepad.viper-7.com/ZYNrNd打印的数组的第三个元素).我会调查一下.

另一方面,一个简单的方法是使用RecursiveArrayIterator:

$flattenedArray = array();
foreach (new RecursiveIteratorIterator(
             new RecursiveArrayIterator($baseArray),
             RecursiveIteratorIterator::LEAVES_ONLY
         ) as $value) {
    $flattenedArray[] = $value;
}
Run Code Online (Sandbox Code Playgroud)