Search code examples
phplaravellaravel-collection

How to persist a value between iterations in a Laravel Collection?


In my app, a Table can seat a certain number of diners. I need to write a collection that returns only the number of Tables I need to seat a given number of diners.

For example, if I have to seat four diners, and only have tables that seat one, I return four tables. If I have a table that seats four or greater, I only return that table.

public function filterTablesWithSeating($numberOfGuests)
{
    $seats = 0;
    return Table::get()->map(function ($table) use ($seats, $numberOfGuests) {
        if ($seats >= $numberOfGuests) {
            return false; // Break the collection
        }
        $seats = $seats + $table->can_seat;
        return $table;
    });
}

This theoretically accomplishes what I'm trying to do, except that, because $seats is defined outside of the collection, I can't update it directly. With each iteration of the collection, it gets redefined as 0.

Is there a way that I can either:

  1. Persist the $seat variable between iterations
  2. Refactor the collection to return only enough Tables to satisfy my $numberOfGuests

Solution

  • What you want to do is pass your $seats by reference which will allow your loop to update it.

    public function filterTablesWithSeating($numberOfGuests)
    {
        $seats = 0;
        
        // Add the ampersand before your $seats to pass by reference
        return Table::get()->map(function ($table) use (&$seats, $numberOfGuests) {
            if ($seats >= $numberOfGuests) {
                return false; // Break the collection
            }
            $seats = $seats + $table->can_seat;
            return $table;
        });
    }