Delicious Bookmark this on Delicious Share on Facebook SlashdotSlashdot It! Digg! Digg



PHP : Function Reference : Array Functions : array_walk_recursive

array_walk_recursive

Apply a user function recursively to every member of an array (PHP 5)
bool array_walk_recursive ( array &input, callback funcname [, mixed userdata] )

Applies the user-defined function funcname to each element of the input array. This function will recur into deeper arrays. Typically, funcname takes on two parameters. The input parameter's value being the first, and the key/index second. If the optional userdata parameter is supplied, it will be passed as the third parameter to the callback funcname.

Returns TRUE on success or FALSE on failure.

Note:

If funcname needs to be working with the actual values of the array, specify the first parameter of funcname as a reference. Then, any changes made to those elements will be made in the original array itself.

Example 290. array_walk_recursive() example

<?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');
?>

The above example will output:

a holds apple
b holds banana
sour holds lemon ?>

You may notice that the key 'sweet' is never displayed. Any key that holds an array will not be passed to the function.


See also array_walk(), and information about the callback type.

Code Examples / Notes » array_walk_recursive

ik

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.


omega13a

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.


aidan

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


adam dott pub att adamswick dott com

Thanks to all of you in the prior posts.
I don't like the fact that the current version of array_walk_recursive() doesn't track all array keys.  This version will do that, as well as tracking array depth on multi-dimensional arrays.
- - - - - - -
Class Array_walk_recursive3 {
private $depth = -1;
private $userdata, $funcname;
public $status;
public $input;

public function __construct($input, $funcname, $userdata = "") {
$this->input = $input;
$this->funcname = $funcname;
$this->userdata = $userdata;
$this->status = $this->array_walk_recursive($this->input);
}

private function test_print(&$value, &$key)
{
echo str_repeat("  ", $this->depth)."$key holds ";
if (!is_array($value)) {
echo $value;
if (trim($value) == "banana") {
$value = "cherry";
$key = "c";
}
}
echo "\n";
}

private function array_walk_recursive(&$input) {
$funcname = array(&$this, $this->funcname);
  if (!is_callable($funcname)) {
      return false;
  }

  if (!is_array($input)) {
      return false;
  }
$this->depth++;

  foreach (array_keys($input) AS $keyIdx => $key) {
$saved_value = $input[$key];
       $saved_key = $key;
call_user_func_array($funcname, array(&$input[$saved_key], &$key));

       if ($input[$saved_key] !== $saved_value || $saved_key !== $key) {
$saved_value = $input[$saved_key];
           unset($input[$saved_key]);
           $input[$key] = $saved_value;
       }
      if (is_array($input[$key])) {
if (!$this->array_walk_recursive($input[$key], $funcname)) return false;
$this->depth--;
      }
  }
  return true;
}
}
$sweet = array('a' => 'apple', 'b' => 'banana');
$fruits = array('sweet' => $sweet, 'sour' => 'lemon');
$fruitObj = new Array_walk_recursive3($fruits, 'test_print');
echo $fruitObj->status;
$newFruitArr = $fruitObj->input;
print_r($fruits);
print_r($newFruitArr);


egingell

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;
}
?>


hannes

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 :)


gieterke

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
";
$anObject = new ClassName();
//array_walk_recursive($anObject->getFruits(), 'test_print'); => doesn't work
array_walk_recursive($anObject->getFruits(), array(&$anObject, 'test_print'));
echo"
";
       //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
";
}
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


gabrielu

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);
?>


wileur

A simple way to use callback functions that are defined in a class is to simply pass the class instance and function names as values in an array:
<?php
class testClass {
function callbackFunction($value, $key) {
echo "$key: $value<br />\n";
}
function printArray($foo) {
array_walk_recursive($foo, array($this, 'callbackFunction'));
}
}
?>


cory

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. :-)


Change Language


Follow Navioo On Twitter
array_change_key_case
array_chunk
array_combine
array_count_values
array_diff_assoc
array_diff_key
array_diff_uassoc
array_diff_ukey
array_diff
array_fill_keys
array_fill
array_filter
array_flip
array_intersect_assoc
array_intersect_key
array_intersect_uassoc
array_intersect_ukey
array_intersect
array_key_exists
array_keys
array_map
array_merge_recursive
array_merge
array_multisort
array_pad
array_pop
array_product
array_push
array_rand
array_reduce
array_reverse
array_search
array_shift
array_slice
array_splice
array_sum
array_udiff_assoc
array_udiff_uassoc
array_udiff
array_uintersect_assoc
array_uintersect_uassoc
array_uintersect
array_unique
array_unshift
array_values
array_walk_recursive
array_walk
array
arsort
asort
compact
count
current
each
end
extract
in_array
key
krsort
ksort
list
natcasesort
natsort
next
pos
prev
range
reset
rsort
shuffle
sizeof
sort
uasort
uksort
usort
eXTReMe Tracker