Unfortunately I spent a lot of time trying to permanently apply the effects of a function to an array using the array_walk function when instead array_map was what I wanted. Here is a very simple though effective example for those who may be getting overly frustrated with this function...
<?php
$fruits = array("Lemony & Fresh","Orange Twist","Apple Juice");
print_r($fruits);
echo '<br />';
function name_base($key)
{
$name2 = str_replace(" ", "_", $key);
$name3 = str_replace("&", "and", $name2);
$name4 = strtolower($name3);
echo $name4.'<br />';
return $name4;
}
echo '<br />';
$test = array_map('name_base', $fruits);
$fruits_fixed = $test;
echo '<br />';
print_r($fruits_fixed);
?>
array_walk
(PHP 4, PHP 5)
array_walk — Exécute une fonction sur chacun des éléments d'un tableau
Description
Exécute la fonction funcname définie par l'utilisateur sur chaque élément du tableau array .
array_walk() n'est pas affecté par le pointeur interne du tableau array . array_walk() traversera le tableau en totalité sans se soucier de la position du pointeur.
Liste de paramètres
- array
-
Le tableau d'entrée.
- funcname
-
Typiquement, funcname prend deux paramètres. La valeur du paramètre input étant le premier et la clé/index, le second.
Note: Si funcname doit travailler avec les véritables valeurs du tableau, spécifiez que le premier paramètre de funcname doit être passé par référence. Alors, les éléments seront directement modifiés dans le tableau.
Les utilisateurs ne peuvent pas modifier le tableau lui-même depuis la fonction de rappel. Par exemple, Ajout/Effacement d'éléments, réinitialisation d'éléments, etc. Si le tableau sur lequel array_walk() est appliqué est changé, le comportement de la fonction est indéfini et non prévisible.
- userdata
-
Si le paramètre optionnel userdata est fourni, il sera passé comme troisième paramètre à la fonction définie par l'utilisateur funcname .
Valeurs de retour
Cette fonction retourne TRUE en cas de succès, FALSE en cas d'échec.
Erreurs / Exceptions
Si function requiert plus de paramètres que ceux donnés, une alerte E_WARNING sera générée à chaque fois que la fonction array_walk() appellera funcname . Ces alertes peuvent ne pas être affichées en utilisant l'opérateur d'erreur PHP @ lors de l'appel de la fonction array_walk() ou en utilisant error_reporting().
Historique
| Version | Description |
|---|---|
| 4.0.0 | Le passage de la clé et du paramètre userdata à funcname ont été ajoutés. |
Exemples
Exemple #1 Exemple avec 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 "Avant ...:\n";
array_walk($fruits, 'test_print');
array_walk($fruits, 'test_alter', 'fruit');
echo "... et après :\n";
array_walk($fruits, 'test_print');
?>
L'exemple ci-dessus va afficher :
Avant ...: d. lemon a. orange b. banana c. apple ... et après : d. fruit: lemon a. fruit: orange b. fruit: banana c. fruit: apple
Voir aussi
- array_walk_recursive()
- iterator_apply()
- create_function()
- list()
- each()
- call_user_func_array()
- array_map()
- information à propos de callback type
- foreach
array_walk
27-Nov-2008 01:08
16-Nov-2008 06:04
I had some problems using this function - it didn't want to apply PHP-defined functions. So I decided to write my own - here it is. I had to use some generic-programming skills, didn't really checked the speed (I think it could be slow)... I believe it could be much better, but I don't know, how - well, I guess multiple array support and recursion would be nice. So?
Prototype:
bool arrayWalk(array &$arry, callback $callback, mixed $params=false)
<?php
function arrayWalk(&$arry, $callback, $params=false) {
$P=array(""); // parameters
$a=""; // arguement string :)
if($params !== false) { // add parameters
if(is_array($params)) { // multiple additional parameters
foreach($params as $par)
{ $P[]=$par; }
}
else // just one additional
{ $P[]=$params; }
}
for( // create the arguement string
$i=0; isset($P[$i]); ++$i
)
{ $a.='$'.chr($i + 97).', '; } // random argument names
$a=substr($a, 0, -2); // to get rid of the last comma and two spaces
$func=create_function($a, 'return '.$callback.'('.$a.');'); // the generic function
if(is_callable($func)) {
for( // cycle through array
$i=0; isset($arry[$i]); ++$i
) {
$P[0]=$arry[$i]; // first element must be the first argument - array value
$arry[$i] = call_user_func_array($func, $P); // assign the new value obtained by the generic function
}
}
else
{ return false; } // failure - function not callable
return true; // success!
} // arrayWalk()
?>
One big problem I've noticed so far - for example, if you wanted to use str_replace on the array, you'd fail - simply because of the arguement order of str_replace, where the string modified is the third arguement, not the first as arrayWalk requires.
So, still some work left...
31-Oct-2008 08:18
When i pass the third parameter by reference in php5.2.5,
happened this: Warning: Call-time pass-by-reference has been deprecated - argument passed by value...
And to set allow_call_time_pass_reference to true in php.ini won't work, according to http://bugs.php.net/bug.php?id=19699 thus to work around:
<?php
array_walk($arrChnOut, create_function('&$v, $k, $arr_rtn', 'if ($k{0}!="_") {$arr_rtn[0]["_".$v[\'ID\']]=$v; unset($arr_rtn[0][$k]);}'), array(&$arrChnOut));
?>
22-Oct-2008 01:04
Although the manual warned you not to unset element, but sometimes thus is very useful and work as charm:
<?php
$arrChnOut=array(0=>array('ID' => '13',
'ChannelName' => 'Computers'
),
1=>array('ID' => '17',
'ChannelName' => 'Computers'
),
2=>array('ID' => '18',
'ChannelName' => 'Computers'
),
);
array_walk($arrChnOut, create_function('&$v, $k, $arr_rtn', 'if ($k{0}!="_"){$arr_rtn["_".$v[\'ID\']]=$v;unset($arr_rtn[$k]);}'), &$arrChnOut);
var_export($arrChnOut);
?>
10-Sep-2008 03:21
@puremango dot co dot uk at gmail dot com
Don't know which version requires putting the class and function into an array to get the function recognized by php, but as of 5.2.4 at least, you can do just "class_name::function" as the function parameter here for statically defined functions. Either way tested just the same.
07-Sep-2008 05:10
On array_walk and create_function used within a class scope - Anonymous functions are out of scope. So, if you want to access $this within the anonymous function, you'd have to pass it through the third parameter...
<?php
// example copies all values into $this where key is the same as property name
array_walk($array, create_function('$v,$k,&$that', 'if (property_exists($that,$k)) {$that->$k = $v;}'), $this);
// or, switch it around and array_walk the object
array_walk($this, create_function('&$v,$k,$array','if (array_key_exists($k,$array)) {$v = $array[$k];}'), $array);
?>
02-Jul-2008 09:49
to array_walk with a function defined in a class, try this:
<?php
// An example callback method
class MyClass {
static function myCallbackMethod($data) {
return $data.$data;
}
}
$my_array = array('one','two','three');
// Static class method cal
array_walk($my_array,array('MyClass', 'myCallbackMethod'));
?>
returns array('oneone','twotwo','threethree');
code from: http://uk.php.net/manual/en/language.pseudo-types.php
thought it would be useful here.
11-Jun-2008 10:18
@harmor
<?php
function array_trim($arr) {
return array_map('trim', $arr);
}
?>
09-May-2008 09:23
I just wanted a function to trim all the array elements. Here is a non-recursive version:
<?php
$data = array(' a',' b',' c d ');
function _trim(&$value)
{
$value = trim($value);
}
function array_trim($arr)
{
array_walk($arr,"_trim");
return $arr;
}
$arr = array_trim($data);
echo '<pre>';
var_dump($arr);
echo '</pre>';
$single = implode(' ',$arr);
echo '<pre>';
var_dump($single);
echo '</pre>';
?>
Output:
array(3) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(10) "c d"
}
string(14) "a b c d"
23-Mar-2008 12:24
hioctiane at hioctiane dot de and ibolmo
<?php
class walker
{
public function walk(&$str_or_arr, $method, $string_or_object = NULL)
{
if ( is_array($string_or_object) )
{
$this->an_array(&$str_or_arr, $method, $string_or_object);
}
elseif ( is_string($string_or_object) )
{
$this->a_string(&$str_or_arr, $method, $string_or_object);
}
else
{
return false;
}
}
private function an_array(&$array, $method, $object = NULL)
{
//when argument object is given
if ( isset($object) )
{
//check if it is object
if (!is_object($object))
{
return false;
}
//check if _object_ has method
if ( !array_search( strtolower($method), get_class_methods( get_class($object) ) ) ) )
{
return false;
}
}
else
{
//check if _this_ class has method
if ( !array_search( strtolower($method), get_class_methods( get_class($this) ) ) )
{
return false;
}
}
foreach ($array as $key => $value)
{
//$value is array
if( is_array($value) )
{
//recursiv call of walk_multi_array
$result[$key] = $this->walk_multi_array(&$value, $method, $object);
}
//$value is value
else
{
if (is_object($object))
{
$result[$key] = $object->$method($value);
}
else
{
$result[$key] = $this->$method($value);
}
}
}
return $result;
}
private function a_string(&$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;
}
}
}
?>
06-Mar-2008 09:01
<?php
/**
* class.ArrayTool.php lets you search an array based on key => value pairs
*
* @version 1.0
* @ 1-11-2008
* @author Mike Volmar
*
* Object for converting between array key and value
*
*/
class ArrayTool {
var $mydata = array();
var $flag = 0;
var $results;
function ArrayTool(){
}
function tellAll(){
print_r($this->mydata);
}
function setArray($data){
$this->mydata = $data;
}
function getKey($input){
foreach($this->mydata as $key => $value){
if(($this->flag == 0)&&($input == $value)){
$this->results = $key;
$this->flag = 1;
}
}
$this->flag = 0;
return $this->results;
}
function getValue($input){
foreach($this->mydata as $key => $value){
if(($this->flag == 0)&&($input == $key)){
$this->results = $value;
$this->flag = 1;
}
}
$this->flag = 0;
return $this->results;
}
}
?>
19-Jan-2007 09:15
In response to "Andrzej Martynowicz at gmail dot com", regarding the use of array_walk with the optional 3rd parameter being modified by reference:
while your solution works, yet another option is to call array_walk like so:
<?php
array_walk($array1, 'userfunction', &$array2byreference);
function userfunction(&$array1value, $key, $array2){
// process $array1value and $array2, $array2 will retain the values
}
?>
22-Dec-2006 11:00
<?php
/*Thanks to Jerk, thats what I need all the time.
I have a little Upgrade to your code.
Now the values of your $array will be handled by a consign method from a consign object(optional, otherwise taking this operator).*/
class user_function {
function user_function() {
}
/**
*
* handle all values from multidimensional array by $function from $object
*
*/
function walk_multi_array(&$array, $method, $object=NULL) {
//when argument object is given
if (is_object($object)) {
//check if it is object
if (!is_object($object))
return false;
//check if object has method
if (!array_search(strtolower($method), get_class_methods(get_class($object))))
return false;
}
//no argument object is given
else {
//check if this class has method
if (!array_search(strtolower($method), get_class_methods(get_class($this))))
return false;
}
foreach ($array as $key => $value) {
//$value is array
if(is_array($value))
//recursiv call of walk_multi_array
$result[$key] = $this->walk_multi_array(&$value, $method, $object);
//$value is value
else {
if (is_object($object))
$result[$key] = $object->$method($value);
else
$result[$key] = $this->$method($value);
}
}
return $result;
}
}
class test_class {
function test_class() {
}
function strtoup($value) {
return strtoupper($value);
}
}
$test_class = new test_class;
$user_function = new user_function;
$array = array (
1 => "testFall1",
2 => array (
21 => "tesTfaLL21",
22 => array (
221 => "TESTFALL221",
222 => "testfall222"
)
),
3 => "testfall3"
);
echo "<pre>";
print_r($user_function->walk_multi_array($array, 'strtoup', $test_class));
echo "</pre>";
?>
Output:
Array
(
[1] => TESTFALL1
[2] => Array
(
[21] => TESTFALL21
[22] => Array
(
[221] => TESTFALL221
[222] => TESTFALL222
)
)
[3] => TESTFALL3
)
21-Dec-2006 05:05
if you want to modify every value of an multidimensional array use this function used here:
<?php
$array = array (1=>1, 2=> 2, 3 => array(1=>11, 2=>12, 3=>13));
$text = "test";
function modarr(&$array, $text) {
foreach ($array as $key => $arr) {
if(is_array($arr)) $res[$key] = modarr(&$arr,$text);
// modification function here
else $res[$key] = $arr.$text;
}
return $res;
}
$erg = modarr($array, $text);
print_r($erg);
?>
result will be_
<?php
Array ( [1] => 1test [2] => 2test [3] => Array ( [1] => 11test [2] => 12test [3] => 13test ) )
?>
06-May-2006 12: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.
<?php
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;
}
}
?>
21-Nov-2005 03: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.
18-Nov-2005 04: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
?>
31-Oct-2005 03: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', )
19-Sep-2005 03: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.
18-Jul-2005 09: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.
27-May-2005 12: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
23-May-2005 07: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.
08-Apr-2005 08: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.
17-Jan-2005 03: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.
11-Nov-2004 02: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);
}
}
If array_walk_recursive() is not present and you want to apply htmlentities() on each array element you can use this:
<?php
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.
16-Oct-2004 04: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
}
}
04-Sep-2004 01: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.
03-Sep-2004 09: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'));
03-Sep-2004 03: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
