1

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
}

1 Answers1

5

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);

Wreigh
  • 3,215
  • 16
  • 37