Bug #79041 [Com]: PHP 7.4 changed foreach behavior for DateTime object

From: Date: Tue, 09 Feb 2021 12:53:23 +0000
Subject: Bug #79041 [Com]: PHP 7.4 changed foreach behavior for DateTime object
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-232024@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79041&edit=1

 ID:                 79041
 Comment by:         drodriguez816 at gmail dot com
 Reported by:        robert at korulczyk dot pl
 Summary:            PHP 7.4 changed foreach behavior for DateTime object
 Status:             Assigned
 Type:               Bug
 Package:            Date/time related
 PHP Version:        7.4.1
 Assigned To:        derick
 Block user comment: N
 Private report:     N

 New Comment:

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


Previous Comments:
------------------------------------------------------------------------
[2020-01-20 17:09:02] 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.

------------------------------------------------------------------------
[2020-01-10 20:23:21] 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-01 21:28:52] 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.

------------------------------------------------------------------------
[2019-12-30 16:15:11] 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.

------------------------------------------------------------------------
[2019-12-28 11:58:01] 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"}
[]


------------------------------------------------------------------------



--
Edit this bug report at https://bugs.php.net/bug.php?id=79041&edit=1


Thread (7 messages)

« previous php.bugs (#232024) next »