The DateTime
class and its friends introduced in PHP 5.2 are a very nice replacement
for the old date & time processing functions (date()
, getdate()
, strftime()
, strtotime()
and so on).
But they come with a minor glitch that is hidden in the plain sight: they are objects and as all the other objects in PHP, they are assigned and passed as parameters by reference[1] and not as copies.
Most of the time I think of a DateTime as a Value Object
, passing it from here to there
without special precautions. And most of the times this works just fine as long as the code doesn’t
try to change it.
When it starts wreaking havoc I remember that DateTime
is a class, the instances of it are objects
and are passed by reference[1] both as method arguments and as their
return values. And special precautions needs to be taken when a method starts modifying
a DateTime
instance that was not created by the same object (because the one that created it
might still hold a reference to it).
The bottom line: always clone the DateTime
objects that were not created by the current function
when you intend to change them.
Later edit (August 2017)
Since PHP 5.5 it’s better to use DateTimeImmutable
objects whenever it’s possible.
They cannot be modified after they are created (they behave like true Value Objects). The methods declared
in DateTimeInterface
that modify the DateTime
objects automatically create
and return clones for DateTimeImmutable
objects.
PHP 5.5 was 20 months old at the time when I wrote this post, but I was still working with PHP 5.3 and PHP 5.4 because of the business constraints.
[1] The PHP documentation explains that they are not really references but different variables storing the same object identifier (which involves an additional redirection layer). This makes them work more like pointers but this is just an implementation detail. From the outside they look like they are passed by reference.