Quelle différence entre DateTime et DateTimeImmutable en PHP ?
Il existe en PHP deux classes pour gérer et manipuler nativement les dates: DateTime
et DateTimeImmutable
. Je me rends compte que de nombreux développeurs ne maitrisent pas la différence entre les deux notions. Ce billet est l’occasion de voir pourquoi et dans quel cas utiliser l’un ou l’autre.
Comme leur nom peut l’indiquer, la différence de fonctionnement est relative à la mutabilité de l’objet manipulé. Dans le cas de DateTime
, l’instance de notre objet sera mutable. Cela signifie que la valeur de ce dernier peut être modifiée après sa création. Prenons le bout de code suivant qui va calculer une date prévisionnelle d’envoi d’une commande:
Dans l’exemple précédent, on peut voir que l’appel à la méthode getExpectedShippingDate
a modifié la valeur de la date de notre objet $orderDate
. En PHP les objets étant passés par référence et une instance de DateTime
étant mutable, toute modification effectuée sur notre objet dans un bloc de code modifie la valeur de ce dernier dans le reste du code.
Pour éviter ce problème, vous l’aurez deviné, il faut utiliser une instance de DateTimeImmutable
. Reprenons le code de notre fonction de calcul de la date prévisionnel d’envoi d’une commande:
Contrairement à une instance de DateTime
, DateTimeImmutable
est un objet immuable. Cela signifie que lorsqu’une opération est effectuée sur ce dernier, PHP ne va pas modifier la valeur courante l’objet. Le moteur va créer une nouvelle instance de date avec la bonne valeur et la renvoyer comme résultat de la fonction. De ce fait, notre date $orderDate
conserve sa valeur d’origine.
A partir de là, la question que l’on est en droit de se poser maintenant est: dans quel cas utiliser l’un ou l’autre ? Au risque de paraître un peu extrémiste, mon avis est que l’on ne devrait jamais utiliser DateTime
. Le risque de créer un effet de bord est trop important, sans compter la difficulté à retrouver l’origine du problème. L’utilisation de DateTime
étant à mon sens à proscrire, vous devriez systèmatiquement utiliser DateTimeImmutable
.