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: 2020-01-20 17:09 UTC
Votes:1
Avg. Score:4.0 ± 0.0
Reproduced:1 of 1 (100.0%)
Same Version:1 (100.0%)
Same OS:0 (0.0%)
From: robert at korulczyk dot pl Assigned: derick (profile)
Status: Assigned Package: Date/time related
PHP Version: 7.4.1 OS:
Private report: No CVE-ID: None
Have you experienced this issue?
Rate the importance of this bug to you:

 [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

Add a Patch

Pull Requests

Add a Pull Request

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.
 
PHP Copyright © 2001-2020 The PHP Group
All rights reserved.
Last updated: Sat Sep 19 17:01:25 2020 UTC