array_walk

(PHP 3 >= 3.0.3, PHP 4, PHP 5)

array_walk -- 对数组中的每个成员应用用户函数

说明

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

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

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

如果 funcname 函数需要的参数比给出的多,则每次 array_walk() 调用 funcname 时都会产生一个 E_WARNING 级的错误。这些警告可以通过在 array_walk() 调用前加上 PHP 的错误操作符 @ 来抑制,或者用 error_reporting()

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

注: 将键名和 userdata 传递到 funcname 中是 PHP 4.0 新增加的。

array_walk() 不会受到 array 内部数组指针的影响。array_walk() 会遍历整个数组而不管指针的位置。

用户不应在回调函数中改变该数组本身。例如增加/删除单元,unset 单元等等。如果 array_walk() 作用的数组改变了,则此函数的的行为未经定义,且不可预期。

例子 1. array_walk() 例子

<?php
$fruits
= array("d" => "lemon", "a" => "orange", "b" => "banana", "c" => "apple");

function
test_alter(&$item1, $key, $prefix)
{
    
$item1 = "$prefix: $item1";
}

function
test_print($item2, $key)
{
    echo
"$key. $item2<br />\n";
}

echo
"Before ...:\n";
array_walk($fruits, 'test_print');

array_walk($fruits, 'test_alter', 'fruit');
echo
"... and after:\n";

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

上例将输出:

Before ...:
d. lemon
a. orange
b. banana
c. apple
... and after:
d. fruit: lemon
a. fruit: orange
b. fruit: banana
c. fruit: apple

参见 array_walk_recursive()create_function()list()foreacheach()call_user_func_array()array_map() 和有关 callback 类型的信息。


add a note add a note User Contributed Notes
nihaopaul at nihaopaul dot com
06-May-2006 06:59
no sure if this should go under array-walk but it does what i need, it searches a multidimensionial array by using an array to walk it, it either returns a value or an array.

function walker($walk, $array) {
   if (count($walk) >0) {
       foreach($array as $key => $value) {
           if ($key == $walk[0]) {
               if (is_array($value)) {
                   unset($walk[0]);
                   return walker(array_values($walk), $value);
               } else {
                   if (isset($value)) {
                       if (count($walk) == 1) {
                           return $value;
                       } else {
                           return 0;
                       }
                   } else {
                       return 0;
                   }
               }
           }
       }
       return 0;
   } else {
       return $array;
   }
}
ludvig dot ericson at gmail dot com
21-Nov-2005 10:09
In response to 'ibolmo', this is an extended version of string_walk, allowing to pass userdata (like array_walk) and to have the function edit the string in the same manner as array_walk allows, note now though that you have to pass a variable, since PHP cannot pass string literals by reference (logically).

<?php
function string_walk(&$string, $funcname, $userdata = null) {
   for(
$i = 0; $i < strlen($string); $i++) {
      
# NOTE: PHP's dereference sucks, we have to do this.
      
$hack = $string{$i};
      
call_user_func($funcname, &$hack, $i, $userdata);
      
$string{$i} = $hack;
   }
}

function
yourFunc($value, $position) {
   echo
$value . ' ';
}

function
yourOtherFunc(&$value, $position) {
  
$value = str_rot13($value);
}

# NOTE: We now need this ugly $x = hack.
string_walk($x = 'interesting', 'yourFunc');
// Ouput: i n t e r e s t i n g

string_walk($x = 'interesting', 'yourOtherFunc');
echo
$x;
// Output: vagrerfgvat
?>

Also note that calling str_rot13() directly on $x would be much faster ;-) just a sample.
ibolmo
18-Nov-2005 11:53
If anyone is interested to implement the array_walk functionality to a string. I've made this handy function. Note that this can be easily extended for any type of purpose. I've used this to convert from a string of bytes to a hex string then back from hex to a byte string.
<?php
function string_walk($string,$funcname)
{
   for(
$i=0;$i<strlen($string);$i++) {
      
call_user_func($funcname,$string{$i});
   }
}

function
yourFunc($val)
{
   echo
$val.' ';
}

string_walk('interesting','yourFunc');
//ouput: i n t e r e s t i n g
?>
thomas dot hebinck at digionline dot de
31-Oct-2005 10:07
This is a short way to concatenate a string to each element of an array:

$arr=array(1,2,3,4,5,6,7,8,9,0);
$str=' test'; // must not include ' or " ...

array_walk($arr,create_function('&$elem','$elem .= "' . $str . '";'));

var_export($arr);

The output is:
array ( 0 => '1 test', 1 => '2 test', 2 => '3 test', 3 => '4 test', 4 => '5 test', 5 => '6 test', 6 => '7 test', 7 => '8 test', 8 => '9 test', 9 => '0 test', )
Andrzej Martynowicz at gmail dot com
19-Sep-2005 09:03
It can be very useful to pass the third (optional) parameter by reference while modifying it permanently in callback function. This will cause passing modified parameter to next iteration of array_walk(). The exaple below enumerates items in the array:

<?
function enumerate( &$item1, $key, &$startNum ) {
  
$item1 = $startNum++ ." $item1";
}

$num = 1;

$fruits = array( "lemon", "orange", "banana", "apple");
array_walk($fruits, 'enumerate', $num );

print_r( $fruits );

echo
'$num is: '. $num ."\n";
?>

This outputs:

Array
(
   [0] => 1 lemon
   [1] => 2 orange
   [2] => 3 banana
   [3] => 4 apple
)
$num is: 1

Notice at the last line of output that outside of array_walk() the $num parameter has initial value of 1. This is because array_walk() does not take the third parameter by reference.. so what if we pass the reference as the optional parameter..

<?
$num
= 1;

$fruits = array( "lemon", "orange", "banana", "apple");
array_walk($fruits, 'enumerate', &$num ); // reference here

print_r( $fruits );

echo
'$num is: '. $num ."\n";
echo
"we've got ". ($num - 1) ." fruits in the basket!";
?>

This outputs:
Array
(
   [0] => 1 lemon
   [1] => 2 orange
   [2] => 3 banana
   [3] => 4 apple
)
$num is: 5
we've got 4 fruits in the basket!

Now $num has changed so we are able to count the items (without calling count() unnecessarily).

As a conclusion, using references with array_walk() can be powerful toy but this should be done carefully since modifying third parameter outside the array_walk() is not always what we want.
webmaster at tmproductionz dot com
19-Jul-2005 03:54
to the note right before this one.  that will only trim leading and trailing white space. if you want to trim white space inside the string (ie 'hello    world' to 'hello world') you should use this:

$val = preg_replace ( "/\s\s+/" , " " , $val ) ;

this will also trim leading and trailing white space.
el_porno at web dot de
27-May-2005 06:03
You want to get rid of the whitespaces users add in your form fields...?
Simply use...:

class SomeVeryImportantClass
{
...
   public function mungeFormData(&$data)
   {
       array_walk($data, array($this, 'munge'));
   }

   private function munge(&$value, &$key)
   {
       if(is_array($value))
       {
           $this->mungeFormData($value);
       }
       else
       {
           $value = trim($value);
       }
   }
...
}

so...
$obj = new SomeVeryImportantClass;
$obj->mungeFormData($_POST);
___
eNc
caliban at darklock dot com
24-May-2005 01:33
> I believe this relies on the deprecated runtime
> pass-by-reference mechanism

The array() keyword is a language construct, not a function, so I don't think this is applicable.
Enlightened One
08-Apr-2005 02:17
Beware that "array ($this, method)" construct. If you're wanting to alter members of the "$this" object inside "method" you should construct the callback like this:

  $callback[] = &$this;
  $callback[] = method;
  array_walk ($input, $callback);

Creating your callback using the array() method as suggested by "appletalk" results in a copy of $this being passed to method, not the original object, therefor any changes made to the object by method will be lost when array_walk() returns. While you could construct the callback with "array(&$this, method)", I believe this relies on the deprecated runtime pass-by-reference mechanism which may be removed in future releases of PHP. Better to not create a dependence on that feature now than having to track it down and fix it in the future.
Hayley Watson
17-Jan-2005 10:27
As well as being able to pass the array the callback will be working on by reference, one can pass the optional userdata parameters by reference also:
<?php

function surprise($x,$key,$xs)
{
  
//$key is unused here.
  
$x.='!';
  
array_push($xs,$x);
}

$array1 = array('this','that','the other');
$array2 = array();

array_walk($array1,'surprise',&$array2);

print_r($array1);
print_r($array2);
?>
Of course, that precise example would be better handled by array_map, but the principle is there.
appletalk at gmail dot com
23-Dec-2004 10:26
To use array_walk with a class simply do:
array_walk($input, array($this, method) );
memandeemail at gmail dot com
11-Nov-2004 09:24
If you are using array_walk on a class, dont will work

so ... try this on your own class:

class your_own_class {
   /**
   * @return void
   * @param array $input
   * @param string $funcname
   * @desc A little workaround, do the same thing.
   */
   function array_walk($input, $funcname) {
       foreach ($input as $key => $value) $this->$funcname($value, $key);
   }
}
05-Nov-2004 03:22
If array_walk_recursive() is not present and you want to apply htmlentities() on each array element you can use this:

function array_htmlentities(&$elem)
{
  if (!is_array($elem))
  {
   $elem=htmlentities($elem);
  }
  else
  {
   foreach ($elem as $key=>$value)
     $elem[$key]=array_htmlentities($value);
  }
  return $elem;
} // array_htmlentities()

If you want to output an array with print_r() and you have html in it this function is very helpful.
lgaga dot dont dot spam at muszaki dot info
16-Oct-2004 10:31
Behaviour like array_walk_recursive() can be achieved in php <=5 by a callback function to array_walk() similar to this:

function walkcallback(&$val,$key) {
   if (is_array($val)) array_walk($val,'walkcallback',$new);
   else {
       // do what you want with $val and $key recursively
   }
}
bisqwit at iki dot fi
04-Sep-2004 07:54
It's worth nothing that array_walk can not be used to change keys in the array.
The function may be defined as (&$value, $key) but not (&$value, &$key).
Even though PHP does not complain/warn, it does not modify the key.
paul at heliosville dot com
04-Sep-2004 03:13
one rather important note that was lost in the Great PHP Doc Note Purge of '04 is that you can call methods using array_walk(). Let's assume that we have a class named 'Search', in which there is a method called 'convertKeywords'. Here's how you would call that convertKeywords method from inside the class:

   array_walk($keywords, array($this, 'convertKeywords'));

Notice that, instead of giving a string as the second argument, you give an array with two items: the variable that holds the class (in this case, $this), and the method to call. Here's what it would look like if you were to call convertKeywords from an already-instantiated class:

   $search = new Search;
   array_walk($keywords, array($search, 'convertKeywords'));
Eierkoek
03-Sep-2004 09:46
normaly the $_GET array will add slashes to the array values. To remove all slashes in this array, i created the folowing code

  set_magic_quotes_runtime (0);
  function StripAllSlashes (&$ArrayGET, $Value)
  {
   if (is_array ($ArrayGET)) array_walk ($ArrayGET, "StripAllSlashes");
   else $ArrayGET = stripslashes ($ArrayGET);
  }
  if (isset ($_GET) && get_magic_quotes_gpc ()) array_walk ($_GET, "StripAllSlashes");

I hope this code was usefull,

Eierkoek