Frage

I'm trying to understand something about arrays in for each loops that might be obvious to many.

When i loop through my multi-dimensional array, i attempt to find sub arrays with no third element. If they have no third element, i want to add a third element to that sub array with a specific value.

$testArray = array (
    array("Green", "Yellow", "Blue"),
    array("Brown", "Silver"),
    array("Orange", "Pink", "Black"),
);

When i use the foreach loop:

foreach ( $testArray as $key => $array ) {
    if (count($array) == '2') {
        $array[] = "None";
    };
}

No errors are thrown but nothing happens. When i use the for each loop:

foreach ( $testArray as $key => $array ) {
    if (count($array) == '2') {
        $testArray[$key][] = "None";
    };
}

It works as expected.

Sorry for the long preamble, my questions is:

Why aren't these two foreach loops doing the same thing? Thanks!

War es hilfreich?

Lösung 2

The problem here lies in the fact that foreach iterates over iterables and sets the iteration variable by value. This means that the $array which you are dealing with in the foreach is not the same value of the $testArray.

To rememdy this (and avoid introducing an $index variable to mutate an item in the array), you will need to tell foreach to pass the value by reference. References are PHP's answer to C-style pointers. If a variable references another, both variables point to the same value, so a modification to the contents of one is in effect a modification to the other. In your foreach, you can use &$array to have the loop pass you the items of $testArray by reference instead of by value:

foreach ( $testArray as $key => &$array ) {
    if (count($array) == '2') {
        $array[] = "None";
    }
}

(Codepad Demo)

This aligns with PHP's references, where one variable can be made to reference another like so:

$a = array(1, 2, 3);
$b = &$a;
$b[] = 4;

print_r($a); // 1, 2, 3, 4

(Codepad Demo)

You experience a similar phenomenon with functions:

function byValue($a) {
    $a[] = 4;
}

function byRef(&$a) {
    $a[] = 5;
}

$a = array(1, 2, 3);

byValue($a);
print_r($a); // 1, 2, 3

byRef($a);
print_r($a); // 1, 2, 3, 5

(Codepad Demo)

The references section of the PHP docs has some examples about this syntax of foreach. Also note this (somewhat) related, but interesting read on foreach and references.


Also, on an unrelated note if you weren't aware: you don't need a semicolon after closing a block with } in PHP unless you're doing something like assigning a closure to a variable:

$someFunc = function($a) { return $a; }; //need one here

if(1 + 2 == 4) {
   echo "I just broke math";
} // but you don't need one here

Andere Tipps

Because you need to access $testArray entries "by reference"

foreach ( $testArray as &$array ) {
    if (count($array) == 2) {
        $array[] = "None";
    };
}
unset($array);

foreach loops do not pass the elements by reference. To get the first array to do what you want, it would have to be:

foreach ( $testArray as $key => &$array ) {
    if (count($array) == '2') {
        $array[] = "None";
    };
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top