9

Is there a way to make this code work without a Warning?

function myFunction($value, $key, &$array)
{
     if (strlen($value)<=2) $array[] = $key.$value;
}
$a = array("aa", "bbb", "cc", "dd");
$resultA = array();
array_walk($a, 'myFunction', &$resultA);
// now '$resultA' should contain: Array([0] => aa0 [1] => cc2 [2] => dd3)

It works, but it always throws this warning message:

Warning: Call-time pass-by-reference has been deprecated in path_to\index.php on line 7

I thought that removing the ampersand from the call should be enough to make the warning disappear, and it is, but, strangely the "array_walk" doesn't acomulate the third parameter if I just specify the & in "myFunction". To make it work there has to be an & in the call too, but then it will trigger the warning.

Further, as a temorary workaround I have tried to set the php.ini var "allow_call_time_pass_reference" to true, but I still get the warning...

I'm wondering that may be there's better/preferred method to apply user-defined functions to each element of an array WITH a passed-by-reference parameter.

4
  • let me know php version. Commented Mar 1, 2011 at 14:02
  • @Guarav 5.3 throws deprecated errors instead, of warning, probably 5.2 Commented Mar 1, 2011 at 14:04
  • Hi, It's version 5.2 running under IIS7. @Andy correct guess :) Commented Mar 1, 2011 at 14:14
  • see stackoverflow.com/questions/526556 Commented Jun 9, 2012 at 7:57

2 Answers 2

17

The short answer is that you can't do that with array walk. However, you do have some alterantives:

Using a closure (available in PHP >= 5.3.0):

$myArray = array();
$callback = function ($key, $value) use (&$myArray) {
    if (strlen($value) <= 2) {
        $myArray[] = $key . $value;
    }
};
array_walk($a, $callback);

Create a filter iterator (Note that this is likely way overkill):

class myFilterIterator extends FilterIterator {
    public function accept() {
        return strlen(parent::current()) <= 2;
    }
    public function current() {
        return parent::key() . parent::current();
    }
}
$it = new myFilterIterator(new ArrayIterator($a));
$newArray = iterator_to_array($it);

There are other ways, but you're appending of key and value really makes things difficult for mapping style solutions...

Sign up to request clarification or add additional context in comments.

2 Comments

I can't use clousures with php 5.2. I will go for txyoji solution as it seems simpler to me specialy because I didn't know about the FilterIterator abstract class, and thus it's more similar to "my average" php code. In any case, thanks for the suggestion!
In the first solution parameters are in the wrong order. They should be ($value, $key)
4

The third parameter to array_walk isn't passed by reference so that's not going to work. Instead of a function, you can use an object method as a callback and accumulate the results in the object.

Class myClass
{
 public values;
 public function myCallback($value,$key)
 {
   if (strlen($value)<=2){
       $this->values[] = $key.$value;
   }
 }
}
$a = array("aa", "bbb", "cc", "dd");
$obj = new myClass();
array_walk($a, array($obj,'myCallback'));

or you could define a global inside the callback function.

function myFunction($value, $key)
{
   global $array;    
   if (strlen($value)<=2) $array[] = $key.$value;
}

both are valid.

2 Comments

In the first solution parameters are in the wrong order. They should be ($value, $key)
@hyponym Good catch. Fixed in the example.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.