Skip to content

Cannot hydrate a DateTime instance created without the constructor #8152

Closed
@nicolas-grekas

Description

@nicolas-grekas

Description

This report applies to DateTime, DateTimeImmutable, DateTimeZone, DateInterval and DatePeriod.

Before PHP 8.2, there used to be a way to create a DateTime object from an uninitialized prototype:

$date = (new \ReflectionClass('DateTime'))->newInstanceWithoutConstructor();
$date->date = '1970-01-01 00:00:00.000000';
$date->timezone_type = 1;
$date->timezone = '+00:00';
$date->__wakeup();

These 3 properties do not exist on DateTime, but they're still returned by serialize($date), that's how I figured out how to hydrate the previous object. And it works perfectly. But since PHP 8.2, a deprecation is triggered because dynamic properties are not allowed.

This means that since 8.2, there is no way to hydrate a DateTime instance that is created without the constructor.

This is an issue in symfony/var-exporter for example, which is a library that provides a way to serialize objects to native PHP code (instead of regular serialization strings.) I cannot figure out a way to make this lib support PHP 8.2 while not triggering a warning.

Note that the engine allows itself to create those dynamic properties even on PHP 8.2. Here is some code to highlight this:

$d = new DateTime();
var_dump($d->date);

$e = unserialize(serialize($d));
var_dump($e->date);

This outputs:

Warning: Undefined property: DateTime::$date in /in/EUrC5 on line 4
NULL
string(26) "2022-02-24 22:26:25.005040"

A simple fix would be to add #[AllowDynamicProperties] to those classes.
Another fix would be to actually declare the corresponding properties as protected.

WDYT?

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions