2

I have array with structure:

Array
(
    [months] => Array
        (
            [01] => Array
                (
                    [0] => 16
                    [1] => 31
                )

            [02] => Array
                (
                    [0] => 16
                    [1] => 25
                    [2] => 10
                    [3] => 15
                )

        )

)

Now I trying to use uasort in loop:

        foreach ($dates['months'] as $month) {
            uasort($month, function($a, $b) {
                return $a <=> $b;
            });
        }

But it's not sorting by days (sub-array of month) - why?

3
  • 1
    what is desired output? Commented Feb 2, 2018 at 11:00
  • 4
    Hard to say without expected, but perhaps you're just missing making $month a reference in the foreach? I.e. as &$month Commented Feb 2, 2018 at 11:01
  • There's no use for a custom comparison in this particular case, just asort($month) will do the same. Commented Feb 2, 2018 at 11:14

1 Answer 1

2

You need to pass $month with reference in foreach loop

foreach ($dates['months'] as &$month) 

uasort() modifies arrays by reference but you modify array that is inside the other array, so months are modified but they are not saved in $dates variable.

It can be easily checked by print_r($dates['months']); after uasort() function in the loop.

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

5 Comments

You should add unset($month); after the loop in such a case, to avoid unwanted side effects.
@CBroe I think it was fixed in PHP 7, In PHP 7, foreach does not use the internal array pointer.
This isn’t about any internal array pointer, but that after the loop $month will still contain the reference to the last array element. This has the potential that you later on overwrite that array element without actually intending to do so, if you were to “re-use” that variable name for a different purpose, say $month = 'January'; Therefor the general recommendation is, if you have to use references in a foreach loop, kill the reference immediately after, to avoid falling into that trap. coderwall.com/p/qx3fpa/…
In that case yes you're right, but it's about naming. If we talk about defensive programming then it's good suggestion to use unset()
Sure, a good “programming discipline” can avoid that problem to begin with. But in a more complex script, maybe even with multiple developers working on it, it just has a huge potential to lead to issues, and due to how it manifests itself, this one can be a particular p.i.t.a. to debug ... Therefor I simply consider it a good practice, same as say always using {...} after if/else, even if there currently might be only on single instruction following them.

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.