Vahn Marty Cagalawan
Vahn Marty Cagalawan

Reputation: 589

Laravel Collection push() not properly working

I am trying to duplicate an item in a collection based on the date range. For example, I have a JSON of this:

{
"title": " 200",
"start": "2017-12-20",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

Now I want to duplicate 6x because there are 6 days from 12-20 to 12-25. Like this:

{
"title": " 200",
"start": "2017-12-20",
"endx": "2017-12-20",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-21",
"endx": "2017-12-21",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-22",
"endx": "2017-12-22",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-23",
"endx": "2017-12-23",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-24",
"endx": "2017-12-24",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

I want this because of the answer from my previous question: Repeat events on FullCalendar base on date start and end

Here is my code:

$events = Event::all();

        foreach ($events as $i => $event) {
            if($event->start != $event->endx)
            {
                $date = $event->start;
                $end = $event->endx;
                while (strtotime($date) <= strtotime($end)) {
                    $new = [];
                    $new = $event;

                    $new->start = $date;
                    $new->endx = $date;

                    $events->push($new);

                    $date = date ("Y-m-d", strtotime("+1 day", strtotime($date)));
                }
            }
        }

        return $events->all();

But the only output I got is that it repeats 6x based on the last date "2017-12-25". Like this:

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

{
"title": " 200",
"start": "2017-12-25",
"endx": "2017-12-25",
"equipment": "Chairs",
"quantity": 200
}

Upvotes: 1

Views: 1413

Answers (1)

Wreigh
Wreigh

Reputation: 3287

The problem is:

$new is an object. The $new that you've pushed to that collection is the same $new that you will be using on the next iteration. To further describe the situation:

$a = new stdClass;
$a->name = "foo";

$myArray = [$a];

var_dump($myArray);
// array(1) {
//  [0]=>
//  object(stdClass)#1 (1) {
//    ["name"]=>
//    string(3) "foo"
//  }
//}

$a->name = "bar";
var_dump($myArray);
// array(1) {
//  [0]=>
//  object(stdClass)#1 (1) {
//    ["name"]=>
//    string(3) "bar"
//  }
//}

$new is being passed by reference to the push method, or some would say, assigned by reference.

That's the magic that is happening in your case, to fix that, you should push a cloned object of $new.

You can trace the push code here: https://github.com/laravel/framework/blob/5.5/src/Illuminate/Support/Collection.php#L1129

Change $events->push($new); to $events->push(clone $new);

Upvotes: 5

Related Questions