PHP 8.0: New DateTime/DateTimeImmutable::createFromInterface()
methods
PHP's DateTime
and DateTimeImmutable
classes have methods to create one instance from another.
DateTime::createFromImmutable(DateTimeImmutable $object): DateTime
DateTimeImmutable::createFromMutable(DateTime $date): DateTimeImmutable
Both DateTime
and DateTimeImmutable
classes implement DateTimeInterface
DateTimeInterface
├── DateTime
└── DateTimeImmutable
In PHP 8.0, both DateTime
and DateTimeImmutable
classes get a new method ::createFromInterface
. They behave exactly as they would in createFromMutable
and createFromImmutable
methods, but the new createFromInterface
method, as its name suggests, accepts any DateTimeInterface
implementation.
DateTime::createFromInterface(DateTimeInterface $object): DateTime
DateTimeImmutable::createFromInterface(DateTimeInterface $object): DateTimeImmutable
Backwards compatibility impact
This is a rather simple improvement in PHP 8.0, and it wouldn't be too difficult to mimic this functionality with instanceof
checks and calling either of the createFrom*
methods available in all PHP versions.
Libraries that extend DateTime
and DateTimeImmutable
can polyfill this functionality with a bit of trait-foo, using a trait
that conditionally declares the createFromInterface
method if it's not available in PHP version it runs on.
class MyCustomDateTime {
use DateTimeCreateFromInterfacePolyfill;
// ...
}
class MyCustomDateTimeImutable {
use DateTimeImmutableCreateFromInterfacePolyfill;
// ..
}
In the appropriately named files (for PSR-4 naming and autoloading), it is now possible to declare the two polyfill traits that will only contain the methods in PHP versions prior to 8.0
// path/to/DateTimeCreateFromInterfacePolyfill.php
if (PHP_VERSION_ID < 80000):
trait DateTimeCreateFromInterfacePolyfill {
public function createFromInterface(\DateTimeInterface $object): \DateTime {
if ($object instanceof \DateTimeImmutable) {
return \DateTime::createFromImmutable($object);
}
if ($object instanceof \DateTime) {
return clone $object;
}
throw new \InvalidArgumentException('Unexpected type');
}
}
else:
trait DateTimeCreateFromInterfacePolyfill {}
endif;
// path/to/DateTimeImmutableCreateFromInterfacePolyfill.php
if (PHP_VERSION_ID < 80000):
trait DateTimeImmutableCreateFromInterfacePolyfill {
public function createFromInterface(\DateTimeInterface $object): \DateTimeImmutable {
if ($object instanceof \DateTime) {
return \DateTimeImmutable::createFromMutable($object);
}
if ($object instanceof \DateTimeImmutable) {
return clone $object;
}
throw new \InvalidArgumentException('Unexpected type');
}
}
else:
trait DateTimeImmutableCreateFromInterfacePolyfill {}
endif;