在多维数组中搜索对象


Searching a multidimensional array for objects

我在PHP中有一个多维数组,希望能够搜索它并找到所有作为对象的值。

我想这样做的原因是,当找到一个对象时,我可以通过调用它的output()方法来用数组替换它。output()方法使用get_object_vars()将自己变成一个数组,然后返回。

这里有一个例子,它可以手动实现我想要的(但只有两个深度级别):

// First level search...
foreach($array as $k => $v) {
    // Check if it's an array.
    if (is_array($v)) {
        // Second level search...
        foreach($v as $k2 => $v2) {
            // If it's an object - convert it!
            if (is_object($v2)) {
                $array[$k][$k2] = $array[$k][$k2]->output();
            }
        }
    }
    // If it's an object - convert it!
    if (is_object($v)) {
        $array[$k] = $array[$k]->output();
    }
}

Tim Cooper的回答是错误的,因为函数必须有一个通过引用而非值传递的参数。

php > class Foo { public function output() { return "this was an object"; } }
php > $a = array( 1 => array( 2 => array( 'foo', 'red', 1, new Foo() ) ) );
php > array_walk_recursive( $a, function( $item, $key ) { 
    if ( is_object( $item ) ) { 
        $item = $item->output(); 
    }
} );
php > print_r( $a );
Array
(
    [1] => Array
        (
            [2] => Array
                (
                    [0] => foo
                    [1] => red
                    [2] => 1
                    [3] => Foo Object
                        (
                        )
                )
        )
)

对照参考:

php > array_walk_recursive( $a, function( &$item, $key ) { 
    if ( is_object( $item ) ) {             
        $item = $item->output();
    } 
} );
php > print_r( $a );
Array
(
    [1] => Array
        (
            [2] => Array
                (
                    [0] => foo
                    [1] => red
                    [2] => 1
                    [3] => this was an object
                )
        )
 )

您只需要一个递归函数:

function objects_to_arrays_recursive (&$array) {
  foreach ($array as &$member) {
    if (is_object($member)) {
      $member = $member->output();
    }
    if (is_array($member)) {
      objects_to_arrays_recursive($member);
    }
  }
}

这将调用每个对象的output()方法,并将结果存储在最初保存该对象的键中。

注意事项

  • 这将在对象转换后循环对象,还将转换子对象。您可能不想这样做,特别是如果您有循环引用,因为这会导致中篇循环。只需将2个if更改为if / elseif就可以避免这种情况
  • 这不会检查给定对象是否有要调用的output()方法。您可能应该添加一个is_a()/instanceof检查
  • 此函数通过引用获取其参数,这意味着将修改输入数组。如果需要保持原始数组的完整性,则需要先对其进行复制