array_walk_recursive

(PHP 5)

array_walk_recursive -- 对数组中的每个成员递归地应用用户函数

说明

bool array_walk_recursive ( array &input, callback funcname [, mixed userdata] )

将用户自定义函数 funcname 应用到 array 数组中的每个单元。本函数会递归到更深层的数组中去。典型情况下 funcname 接受两个参数。input 参数的值作为第一个,键名作为第二个。如果提供了可选参数 userdata,将被作为第三个参数传递给 callback funcname

如果成功则返回 TRUE,失败则返回 FALSE

注: 如果 funcname 需要直接作用于数组中的值,则给 funcname 的第一个参数指定为引用。这样任何对这些单元的改变也将会改变原始数组本身。

例子 1. array_walk_recursive() 例子

<?php
$sweet
= array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');

function
test_print($item, $key)
{
    echo
"$key holds $item\n";
}

array_walk_recursive($fruits, 'test_print');
?>

上例将输出:

a holds apple
b holds banana
sour holds lemon

注意上例中的键 'sweet' 并没有显示出来。任何其值为数组的键都不会被传递到回调函数中去。

参见 array_walk() 和有关 callback 类型的信息。


add a note add a note User Contributed Notes
ik at paulkaspers dot nl
16-Oct-2006 04:46
To egingell at sisna dot com:

There is a small bug in your function, the following line should be changed:
From: if ($value != $saved_value || $saved_key != $key) {
Into: if ($value !== $saved_value || $saved_key !== $key) {

It's a nice function, because I was searching for something to change the keys of a multiple dimension array.
gieterke at gmail dot com
29-Mar-2006 08:59
I think there are a lot of people who want/have to work object oriented.
this is an Object oriented version

the code is written in PHP5
<?php
  
//auto overload classes, so you don't have to put in all the includes
  
function __autoload($class_name) {
       require_once
$class_name . '.php';
   }

   echo
"TESTING: arraywalker<br>";
  
$anObject = new ClassName();

  
//array_walk_recursive($anObject->getFruits(), 'test_print'); => doesn't work
  
array_walk_recursive($anObject->getFruits(), array(&$anObject, 'test_print'));

   echo
"<br><br>";
      
//if you just want to give the array and not hte function name that handles the array
  
$anObject->arrWalker($anObject->getFruits());
?>

<?php
//Class description---------------------------------------------
class ClassName {
  
//Class variables
  
private $sweet = array();
  
private $fruits = array();

  
//Constructor
  
public function __construct(){
      
$this->sweet = array('a' => 'apple', 'b' => 'banana');
      
$this->fruits = array('sweet' => $this->sweet, 'sour' => 'lemon');
   }

  
//public methods
  
public function getFruits(){
       return
$this->fruits;
   }

  
public function test_print($item, $key){
       echo
"$key holds $item\n<br>";
   }

  
public function arrWalker($arr){
      
array_walk_recursive($arr, array(&$this, 'test_print'));

   }
}
?>

the code above gives following input:
TESTING: arraywalker
a holds apple
b holds banana
sour holds lemon

a holds apple
b holds banana
sour holds lemon
egingell at sisna dot com
18-Mar-2006 05:53
Slightly modified version of array_walk_recursive function by "omega13a at sbcglobal dot net"

$function also modifies the keys in addition to the values.

Usefull if you want to trim() the keys and values of an array.

The $key in $funcname would also have to be passed by referrence.

Named 'array_walk_recursive2' since it is not the same as the PHP5 version, you can rename it to 'array_walk_recursive' if you are running PHP4 and have no reason to upgrade.

<?
function funcname(&$value, &$key, $userdata = "") {
  
// Do stuff to $value and $key
}

function
array_walk_recursive2(&$input, $funcname, $userdata = "") {
   if (!
is_callable($funcname)) {
       return
false;
   }

   if (!
is_array($input)) {
       return
false;
   }

   foreach (
$input AS $key => $value) {
       if (
is_array($input[$key])) {
          
array_walk_recursive2($input[$key], $funcname, $userdata);
       } else {
          
$saved_value = $value;
          
$saved_key = $key;
           if (!empty(
$userdata)) {
              
$funcname($value, $key, $userdata);
           } else {
              
$funcname($value, $key);
           }

           if (
$value != $saved_value || $saved_key != $key) {
               unset(
$input[$saved_key]);
              
$input[$key] = $value;
           }
       }
   }
   return
true;
}
?>
gabrielu at hotmail dot com
22-Feb-2006 05:13
I decided to add to the previous PHP 4 compatible version of array_walk_recursive() so that it would work within a class and as a standalone function.  Both instances are handled by the following function which I modified from omega13a at sbcglobal dot net.

The following example is for usage within a class.  To use as a standalone function take it out of the class and rename it.  (Example: array_walk_recursive_2)

<?php
class A_Class {

function
array_walk_recursive(&$input, $funcname, $userdata = '') {
  if(!
function_exists('array_walk_recursive')) {
   if(!
is_callable($funcname))
     return
false;

   if(!
is_array($input))
     return
false;

   foreach(
$input as $key=>$value) {
     if(
is_array($input[$key])) {
       if(isset(
$this)) {
         eval(
'$this->' . __FUNCTION__ . '($input[$key], $funcname, $userdata);');
       } else {
         if(@
get_class($this))
           eval(
get_class() . '::' . __FUNCTION__ . '($input[$key], $funcname, $userdata);');
         else
           eval(
__FUNCTION__ . '($input[$key], $funcname, $userdata);');
       }
     } else {
      
$saved_value = $value;

       if(
is_array($funcname)) {
        
$f = '';
         for(
$a=0; $a<count($funcname); $a++)
           if(
is_object($funcname[$a])) {
            
$f .= get_class($funcname[$a]);
           } else {
             if(
$a > 0)
              
$f .= '::';
            
$f .= $funcname[$a];
           }
        
$f .= '($value, $key' . (!empty($userdata) ? ', $userdata' : '') . ');';
         eval(
$f);
       } else {
         if(!empty(
$userdata))
          
$funcname($value, $key, $userdata);
         else
          
$funcname($value, $key);
       }

       if(
$value != $saved_value)
        
$input[$key] = $value;
     }
   }
   return
true;
  } else {
  
array_walk_recursive($input, $funcname, $userdata);
  }
}

function
kv_addslashes(&$v, $k) {
 
$v = addslashes($v);
}
}
?>

Usage:
<?php
$arr
= array(
 
'a' => '"Hello World"',
 
'b' => "'Hello World'",
 
'c' => "Hello 'Worl\"d",
 
'd' => array(
  
'A' => 'H"e"l"l"o" "W"o"r"l"d'
  
)
  );

$class = new A_Class();
$class->array_walk_recursive($arr, array(&$class, 'kv_addslashes'));
print_r($arr);
?>
omega13a at sbcglobal dot net
22-Dec-2005 08:21
This is a peice of code I wrote that appears to create this function for PHP 4.

<?php
if (!function_exists('array_walk_recursive'))
{
   function
array_walk_recursive(&$input, $funcname, $userdata = "")
   {
       if (!
is_callable($funcname))
       {
           return
false;
       }
      
       if (!
is_array($input))
       {
           return
false;
       }
      
       foreach (
$input AS $key => $value)
       {
           if (
is_array($input[$key]))
           {
              
array_walk_recursive($input[$key], $funcname, $userdata);
           }
           else
           {
              
$saved_value = $value;
               if (!empty(
$userdata))
               {
                  
$funcname($value, $key, $userdata);
               }
               else
               {
                  
$funcname($value, $key);
               }
              
               if (
$value != $saved_value)
               {
                  
$input[$key] = $value;
               }
           }
       }
       return
true;
   }
}
?>

Please note it is a conditionaly set function and will have to be put before any call to it.

If there is anything wrong with it, please email me.
cory at lavacube dot com
07-Dec-2005 06:09
A simple way to implement array_walk_recursive() in PHP 4 is to use to do the following...

<?php

// first, lets define our function
  
function test_array_walkr( &$item, $key )
   {
      
// do what you want to do here - in this example we will
       // check to see if $item is an array. If it is, we will
       // check to see if the key '.hide' exists. If this exists,
       // we will set the entire array to NULL;
      
if( is_array($item) && array_key_exists('.hide', $item) )
       {
          
$item = NULL;
       }

      
// this is the code that causes the recursive effect
       // we do this after, to allow for any changes to $item
       // to be included in the next recursive call...
      
if( is_array($item) )
       {
          
array_walk($item, __FUNCTION__);
       }
   }

// next, let's define our array:
$test = array(
              
'one'    => array('one->one', 'one->two', 'one->three'),
              
'two'    => array('.hide'=>true, 'two->one', 'two->two', 'two->three'),
              
'three'    => array('three->one', 'three->two', 'three->three')
           );

// lets run the test. ;-)
  
array_walk($test, 'test_array_walkr');

// ... and get the results
  
print_r($test);

?>

This example will yeild:
Array
(
   [one] => Array
       (
           [0] => one->one
           [1] => one->two
           [2] => one->three
       )
   [two] =>
   [three] => Array
       (
           [0] => three->one
           [1] => three->two
           [2] => three->three
       )
)

Hope this helps someone. :-)
aidan at php dot net
22-Feb-2005 03:10
This functionality is now implemented in the PEAR package PHP_Compat.

More information about using this function without upgrading your version of PHP can be found on the below link:

http://pear.php.net/package/PHP_Compat
hannes (at) tismer.com
15-Dec-2004 03:08
I wondered about an array_mergedown function working with PHP4, using an array_walk_recursive-like function which just merges any number of arrays of any dimension to a one dimension array containing every key=>value part of all arrays:

<?php
function array_mergedown() {
   global
$outarray;
  
$outarray = array();
   function
array_walk_recphp4(&$val,$key) {
       global
$outarray;
       if (
is_array($val)) array_walk($val,'array_walk_recphp4');
       else {
          
$outarray[$key] = $val;
       }
   }
  
$params = func_get_args();
   foreach (
$params as $subarr) {
      
array_walk_recphp4($subarr, '');
   }
   return
$outarray;
}
?>

For testing:

<?php
$arr1
[]["foo1"] = "bar1";
$arr2["foo2"] = "bar2";
$arr2[12] = "bar3";
$arr2[10]["foo4"] = "bar4";
$arr2[]["foo4"][0]["foo5"] = "bar5";
$arr3 = "nono";

print_r(array_mergedown($arr1, $arr2, $arr3));
?>

returns:
Array ( [foo1] => bar1 [foo2] => bar2 [12] => bar3 [foo4] => bar4 [foo5] => bar5 )

I hope this helped someone :)