Page 1 of 1

adding to an assoc array fails after the loop

Posted: Fri Oct 30, 2009 12:23 pm
by mlecho
i am simply trying to dynamically add a new field to an array of nested assoc arrays. When i do the following:

Code: Select all

 
foreach($data as $d)
        {
        
            $date = $d['Event']['date'];
            $prettyDate = date('M j,Y', strtotime($date));                      
            $d['Event']['prettyDate'] = $prettyDate;    //this works and adds to the $d["Event"] assoc array
        }       
        print_r($data);  //but after the loop, $d["Event"]["prettyDate"] is not appended...why?
 
$d["Event"] is uneffected outside of the loop....however, if i do a print_r($d) in the loop, i see the expected addition of the "prettyDate" to the assoc array. Why does it not stay affected after the loop? And how can i remedy that?

Re: adding to an assoc array fails after the loop

Posted: Fri Oct 30, 2009 12:39 pm
by Mark Baker
foreach($data as &$d)

Re: adding to an assoc array fails after the loop

Posted: Fri Oct 30, 2009 12:57 pm
by mlecho
perfect...
so, to cap the learning curve, what is that "&" called, and where can i learn more about it....

Thanks a ton, by the way, it's perfect

Re: adding to an assoc array fails after the loop

Posted: Fri Oct 30, 2009 4:29 pm
by Mark Baker
Pass by reference. Technically, PHP passes everything be reference now, and it's more commonly seen when passing values to functions.

Although passed by reference, whenever a function argument is modified, PHP clones a copy of the argument within local scope, and it's the copy that is modified.

Code: Select all

 
function test($x,$y) {
    return (++$x * ++$y);
}
 
$A = 2;
$B = 3;
echo test($A,$B);
echo $A;
echo $B;
 
However, when you use the &, PHP doesn't clone a copy when the argument is modified, but modifies the original variable.

Code: Select all

 
function test(&$x,&$y) {
    return (++$x * ++$y);
}
 
$A = 2;
$B = 3;
echo test($A,$B);
echo $A;
echo $B;
 
Within the scope of a foreach loop,

Code: Select all

foreach($data as $d)
$d is a clone of the data element from the array, and any modification to $d is against the cloned copy that is discarded once the loop ends; but if prefixed by &, it's the actual element of the array that is modified.

Note, I forgot to mention, but you should also unset $d once the loop ends, otherwise you may get unpredictable results.

Code: Select all

 
foreach($data as $d) {
    $date = $d['Event']['date'];
    $prettyDate = date('M j,Y', strtotime($date));
    $d['Event']['prettyDate'] = $prettyDate;
}
unset($d);
 
You might think that this would unset the last element in the array, but it doesn't. Using the & with $d actually creates a new variable $d that is a pointer to the array element. Unsetting $d after the loop removes the pointer variable $d, but doesn't unset the array element that it's a pointer to.