php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #79041 PHP 7.4 changed foreach behavior for DateTime object
Submitted: 2019-12-28 11:58 UTC Modified: 2022-07-22 16:20 UTC
Votes:8
Avg. Score:4.5 ± 0.7
Reproduced:7 of 7 (100.0%)
Same Version:5 (71.4%)
Same OS:2 (28.6%)
From: robert at korulczyk dot pl Assigned: derick (profile)
Status: Wont fix Package: Date/time related
PHP Version: 7.4.1 OS:
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: robert at korulczyk dot pl
New email:
PHP Version: OS:

 

 [2019-12-28 11:58 UTC] robert at korulczyk dot pl
Description:
------------
In PHP 7.4 behavior of `foreach (new DateTime() as $property => $value)` has changed. Prior to 7.4 foreach iterates through virtual properties of DateTime object. Since 7.4 it is treated as empty array, which makes it incosistent with `json_encode()` and `(array)` cast. Cast to array was already fixed in https://bugs.php.net/bug.php?id=78383

https://3v4l.org/h99LLn

Context - foreach approach is used in Json helper in Yii 2:
https://github.com/yiisoft/yii2/issues/17760
https://github.com/yiisoft/yii2/blob/a636ff916ac3a06756f37c0dbfb55994394a6a55/framework/helpers/BaseJson.php#L160-L166

Test script:
---------------
$date = new DateTime('2019-12-24');
$properties = [];
foreach ($date as $k => $v) {
    $properties[$k] = $v;
}
var_dump($date);
var_dump((array) $date);
var_dump($properties);
echo json_encode($date), "\n";
echo json_encode((array) $date), "\n";
echo json_encode($properties), "\n";

Expected result:
----------------
object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2019-12-24 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "Europe/Amsterdam"
}
array(3) {
  ["date"]=>
  string(26) "2019-12-24 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "Europe/Amsterdam"
}
array(3) {
  ["date"]=>
  string(26) "2019-12-24 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "Europe/Amsterdam"
}
{"date":"2019-12-24 00:00:00.000000","timezone_type":3,"timezone":"Europe\/Amsterdam"}
{"date":"2019-12-24 00:00:00.000000","timezone_type":3,"timezone":"Europe\/Amsterdam"}
{"date":"2019-12-24 00:00:00.000000","timezone_type":3,"timezone":"Europe\/Amsterdam"}


Actual result:
--------------
object(DateTime)#1 (3) {
  ["date"]=>
  string(26) "2019-12-24 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "Europe/Amsterdam"
}
array(3) {
  ["date"]=>
  string(26) "2019-12-24 00:00:00.000000"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(16) "Europe/Amsterdam"
}
array(0) {
}
{"date":"2019-12-24 00:00:00.000000","timezone_type":3,"timezone":"Europe\/Amsterdam"}
{"date":"2019-12-24 00:00:00.000000","timezone_type":3,"timezone":"Europe\/Amsterdam"}
[]

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2019-12-30 16:15 UTC] nikic@php.net
Not willing to provide BC for this. DateTime doesn't have virtual properties -- it has a debug representation (think __debugInfo()).

To account for that particular use-case it would be nice if DateTime implemented JsonSerializable rather than doing the same via an internal side-channel. Unfortunately that is a bit problematic as json is an optional extension.
 [2020-01-01 21:28 UTC] robert at korulczyk dot pl
Any plans to fix this mess in PHP 8? Current behavior is really confusing, especially with BC hack for `(array)` cast.
 [2020-01-10 20:23 UTC] camporter1 at gmail dot com
Would it be possible to list this in the BC section of the 7.3 to 7.4 migration docs?
 [2020-01-20 17:09 UTC] girgias@php.net
-Assigned To: +Assigned To: derick
 [2020-01-20 17:09 UTC] girgias@php.net
Not sure if this shouldn't be a feature request, assigning to Derick as he is the maintainer of the Date extension.
 [2021-02-09 12:53 UTC] drodriguez816 at gmail dot com
Also there is a problem with reflection.
Reflection is not returning the datetime properties. So $props array will remain empty..

$date = new DateTime();
$reflection = new ReflectionObject($date);
$props = [];

foreach ($reflection->getProperties() as $p) {
    $props[] = $p->getName();
}

var_dump($props);
 [2022-07-22 16:20 UTC] derick@php.net
-Status: Assigned +Status: Wont fix
 [2022-07-22 16:20 UTC] derick@php.net
I'm going to mark this as "won't fix". DateTime(Immutable) does not have real properties, and the once that show up with serialize/json_encode, and (array), are there to handle this specific case.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Dec 21 16:01:28 2024 UTC