web-dev-qa-db-fra.com

Comment copier en profondeur un objet DateTime?

$date1 = $date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));

À présent $date1 et $date2 contiennent la même date - dans trois ans. Je voudrais créer deux dates-heures distinctes, l'une qui est analysée à partir d'une chaîne et l'autre avec trois années ajoutées. Actuellement, je l'ai piraté comme ceci:

$date2 =  new DateTime($date1->format(DateTime::ISO8601));

mais cela semble être un bidouillage horrible. Existe-t-il un moyen "correct" de copier en profondeur un objet DateTime?

113
Billy ONeal
$date1 = new DateTime();
$date2 = new DateTime();
$date2->add(new DateInterval('P3Y'));

Mise à jour:

Si vous voulez copier plutôt que référencer un objet DT existant, utilisez clone, pas =.

$a = clone $b;

154
Amy B

Clonez la date avec l'opérateur clone :

$date1 = new DateTime();
$date2 = clone $date1;
$date2->add(new DateInterval('P3Y'));

Les clones sont peu profonds par défaut, mais suffisamment profonds pour un DateTime. Dans vos propres objets, vous pouvez définir la méthode magique __clone() pour cloner les propriétés (c'est-à-dire les objets enfants) susceptibles d'être clonées lorsque l'objet parent est modifié.

(Je ne sais pas pourquoi la documentation pense que GTK est un bon exemple de la nécessité de cloner un objet. Qui utilise GTK en PHP?)

96
rjmunro

PHP 5.5.0 introduit DateTimeImmutable . Les méthodes add et modify de cette classe renvoient de nouveaux objets.

$date1 = new DateTimeImmutable();
$date2 = $date1->add(new DateInterval('P3Y'));
39
Alexander Garden

TLDR:

$date1 = new DateTime();
$date2 = (clone $date1)->modify('+3 years');

(Une copie superficielle est enrayée - ne copie en profondeur de DateTime (actuellement) non sens)

Aussi simple que cela :)

Explication "php crée un objet datetime depuis un autre datetime":

  1. Le mot-clé clone rend régulier peu profond copier - enaugh pour ce cas (pourquoi => voir ci-dessous)
  2. Le boucler avec () Évalue l'expression renvoyant l'objet nouvellement créé par clone
  3. ->modify() est donc appelé et modifie le nouvel objet
  4. DateTime::modify(...) docs:

    Retourne l'objet DateTime pour le chaînage de méthodes ou FALSE en cas d'échec.

  5. $date2 Contient maintenant le clone/copie nouvellement créé et modifié, tandis que $date1 Reste inchangé

Pourquoi vous n'avez pas besoin de deep copier ici:

La copie en profondeur/clone n’est nécessaire que lorsque vous devez copier des cibles de propriétés qui sont références, mais ceci:

class TestDateTime extends DateTime{
  public function test(){
   //*this* way also outputs private variables if any...
   var_dump( get_object_vars($this) );    
  }
}
$test = (new TestDateTime())->test();

les sorties:

array(3) {
  ["date"]=>
  string(26) "2019-08-21 11:38:48.760390"
  ["timezone_type"]=>
  int(3)
  ["timezone"]=>
  string(3) "UTC"
}

donc il n'y a pas de références, juste des types simples => pas besoin de profond copier.

7
jave.web

Vous devriez changer votre DateTime en DateTimeImmutable

// from date time
$date = \DateTimeImmutable::createFromMutable($mutableDate)

alors vous pouvez appeler n'importe quelle méthode sur le DateTime sans vous soucier de son changement

1
Hossein Shahdoost