Я пытаюсь создать массив периодов (с началом и концом каждого) в цикле, но каждый раз, когда я использую add() для временных переменных, все значения внутри окончательного массива перезаписываются во временную переменную. ценить.
Мой код:
$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
Обобщенный вывод из var_dump($newPeriod)
(как и ожидалось) (значения являются объектами DATETIME)
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"
}
Обобщенный вывод из var_dump($newPeriods)
(не так, как ожидалось, поскольку все значения повторяются):
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"
}
}
ср. DateTimeImmutable против DateTime
Как предложил @MarkusAO в (теперь удаленном) комментарии, использование клона объектов помогло мне:
$newPeriod["start"] = clone end($newPeriods)["start"];
$newPeriod["end"] = clone end($newPeriods)["end"];
Вот как это работает, и вы приказали PHP сделать это таким образом. Обратите внимание, что
DateTime
не является неизменным, если вам нужен неизменяемый вариант, используйте DateTimeImmutable, так как он даст вам новый объект, когда вы добавите к нему точку. в противном случае новый элемент относится к одному и тому же (модифицированному) DateTime (объекту), всегда (это и есть ваш вопрос: он подтверждает указанное поведение и противоречит вашему ожиданию, которое является неизменяемым вариантом, поскольку вам нужны конкретные данные для всех новых периодов каждый ).