phplaravellaravel-7

Adding missing rows of data in a collection - unexplanable Laravel behavior


I have a table of data and I need to fetch an array from it, that looks like this:

[
   ['Mon', 25],
   ['Tue', 13],
   ['Thu', 25]
]

I'm achieving this through some collection acrobatics. At some point I am mapping the collection adding the numerical value of that day (1 Monday, 2 Tuesday) as a key, so I can sortKeys() later.

The problem is not all days are always present and I want to add them with a value of 0 at their respective place.

My first attempt was foreach on an array of days of the week, and if $collection->flatten()->search($day) returns false, prepend that day. This works fine, but Thu always get appended. It never returns true on the search even though it's copied and pasted and should be identical. All other days are skipped/prepended correctly...

Then I tried array_search on toArray() and the same thing happened. Thu never returns true ...

This is extremely weird, basically Thu == Thu returns false

Is there anyway I can use array_merge or something like that to make it better (or get it working at all?).


Solution

  • This is one way of doing it. It could be done much cleaner, if your data was structured different in the first place, like using day name/value as key, instead of having both in sub arrays, but I will keep to the original question:

    $defaultDays = collect([
        ['Mon', 0],
        ['Tue', 0],
        ['Wed', 0],
        ['Thu', 0],
        ['Fri', 0],
        ['Sat', 0],
        ['Sun', 0],
    ]);
    $days        = [
        ['Mon', 25],
        ['Tue', 13],
        ['Thu', 25]
    ];
    
    // Use $defaultDays to map, as we will need all seven days no matter what.
    $days = $defaultDays->map(static function (array $defaultDay) use ($days) {
        // Current match is the default day...
        $match = $defaultDay;
        foreach ($days as $day) {
            if ($day[0] === $defaultDay[0]) {
                $match = $day;
            }
        }
    
        return $match;
    });
    

    This will result in:

    Illuminate\Support\Collection {#1388
      #items: array:7 [
        0 => array:2 [
          0 => "Mon"
          1 => 25
        ]
        1 => array:2 [
          0 => "Tue"
          1 => 13
        ]
        2 => array:2 [
          0 => "Wed"
          1 => 0
        ]
        3 => array:2 [
          0 => "Thu"
          1 => 25
        ]
        4 => array:2 [
          0 => "Fri"
          1 => 0
        ]
        5 => array:2 [
          0 => "Sat"
          1 => 0
        ]
        6 => array:2 [
          0 => "Sun"
          1 => 0
        ]
      ]
    }