0

I'm trying to create an array of periods (with a start and an end each) within a loop but every time I use add() to the temporal variables, all values inside the final array get rewritten to the temporal variable value.

My code:

$newPeriods = []; //final array

$firstPeriod = array(
    "start"=>new DateTime("2022/10/05 16:30:00"), 
    "end"=>new DateTime("2022/10/05 16:45:00")
);

for ($i = 0; $i < 3; $i++) {
    //if not first repetition
    if (isset($newPeriod)) {
        $newPeriod["start"] = end($newPeriods)["start"];
        $newPeriod["end"] = end($newPeriods)["end"];

        //I figured out that the array $newPeriods gets rewriten in the next two lines
        $newPeriod["start"]->add(new DateInterval('P1W'));
        $newPeriod["end"]->add(new DateInterval('P1W'));
    }
    //first repetition
    else {
        $newPeriod['start'] = $firstPeriod["start"];
        $newPeriod['end'] = $firstPeriod["end"];
    }

    var_dump($newPeriod); //this prints what I expect to find in $newPeriods

    array_push($newPeriods, $newPeriod);
}

var_dump($newPeriods);//all elements are like the last $newPeriod

Summarized output from var_dump($newPeriod) (As expected)(Values are DATETIME objects)

array(2) {
  ["start"]=>"2022-10-05 23:55:00.000000"
  ["end"]=>"2022-10-06 00:15:00.000000"
}
array(2) {
  ["start"]=>"2022-10-12 23:55:00.000000"
  ["end"]=>"2022-10-13 00:15:00.000000"
}
array(2) {
  ["start"]=>"2022-10-19 23:55:00.000000"
  ["end"]=>"2022-10-20 00:15:00.000000"
}

Summarized output from var_dump($newPeriods) (not as expected as all values are repeated):

array(3) {
  [0]=>
  array(2) {
    ["start"]=>"2022-10-19 23:55:00.000000"
    ["end"]=>"2022-10-20 00:15:00.000000"
  }
  [1]=>
  array(2) {
    ["start"]=>"2022-10-19 23:55:00.000000"
    ["end"]=>"2022-10-20 00:15:00.000000"
  }
  [2]=>
  array(2) {
    ["start"]=>"2022-10-19 23:55:00.000000"
    ["end"]=>"2022-10-20 00:15:00.000000"
  }
}
  • This is just how it works and you have commanded PHP to do it this way. Note that `DateTime` is _not_ immutable, if you want the immutable variant, use [`DateTimeImmutable`](https://www.php.net/manual/en/class.datetimeimmutable.php) as it will give you a new object when you add a period to it. otherwise the new item refers to the same (modified) DateTime (object), always (which is what your question is: it confirms the specified behaviour, and contradicts your expectation which is the immutable variant as you want concrete data for all new periods each). – hakre Nov 07 '22 at 20:58
  • cf. [DateTimeImmutable vs DateTime](https://stackoverflow.com/q/67536245/367456) – hakre Nov 07 '22 at 21:06

1 Answers1

0

As @MarkusAO suggested in a (now deleted) comment, using a clone of the objects did the trick for me:

$newPeriod["start"] = clone end($newPeriods)["start"];
$newPeriod["end"]   = clone end($newPeriods)["end"];
Tomerikoo
  • 18,379
  • 16
  • 47
  • 61