Bir DateTime nesnesini nasıl derinlemesine kopyalarım?


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

Şimdi $date1ve $date2aynı tarihi ekleyin - bundan üç yıl sonra. Biri bir dizeden ayrıştırılan ve diğeri ona üç yıl eklenen iki ayrı veri zamanı oluşturmak istiyorum. Şu anda bunu şu şekilde hackledim:

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

ama bu korkunç bir hack gibi görünüyor. Bir DateTime nesnesini derinlemesine kopyalamanın "doğru" bir yolu var mı?

Yanıtlar:


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

Güncelleme:

Mevcut bir DT nesnesine başvurmak yerine kopyalamak istiyorsanız, kullanın clone, değil =.

$a = clone $b;


12
Örnekte noktayı göstermek için yeni bir DateTime kullandım, ancak şimdilik DateTime'ın tekrar arayamayacağım bazı opak API'den döndürüldüğünü varsayın. Örneğin, müşterinin bir sonraki sipariş verebileceği bir DateTime döndüren siparişleri işleyen bir işlevim var. Bir kopya oluşturmak için işlevi çağırmak istemediğim yan etkiler yaratır.
Billy ONeal

Aslında test etmedim, ancak php.net'te bunun sadece PHP 5.3 ve üstü için geçerli olduğu belirtiliyor.
hugo der hungrige

@hugo: Evet, DateTime sınıfı PHP 5.3 gerektirir.
Billy ONeal

11
Tam PHP'yi kavradığımı düşündüğümde, yeni bir operatör hakkında bilgi edindim.
kr094

Mevcut bir Carbon nesnesini başka bir değişkene kopyalamak için bunu yapmak gerekiyordu. Bu işe yaradı.
racl101

111

Tarihi klonlama operatörüyle klonlayın :

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

Klonlar varsayılan olarak sığdır, ancak bir DateTime için yeterince derindir. Kendi nesnelerinizde, __clone()ana nesne değiştiğinde klonlanması mantıklı olan özellikleri (yani alt nesneler) klonlamak için sihirli yöntemi tanımlayabilirsiniz .

(Belgelerin neden bir nesneyi klonlama ihtiyacının GTK olduğunu düşündüğünden emin değilim. GTK'yı PHP'de kim kullanır?)


1
Cevabınız için teşekkürler, ancak bunun DateTime için yeterince derin olduğunu nereden biliyorsunuz? Hangi nitelikler referans olarak kalır ve hangileri değere göre kopyalanır? Örneğin, saati ve saat dilimini değiştirebilirim ve bu klonu etkilemez mi?
David

1
@David: DateTime için yeterince derin olduğunu biliyorum çünkü denedim ve benim için çalıştı. Saat dilimini veya başka herhangi bir şeyi değiştirmeyi denemedim, sadece temel saat ve tarihi değiştirmeyi denemedim.
rjmunro

3
Var_dump ($ date1), Xdebug kullanarak, 'date' => string, 'timezone_type' => int & 'timezone' => string içerdiğini bildirir. Herhangi bir dizi veya nesne içermediği için, sadece temel skalarlar, sığ bir klon iyi olmalıdır.
CJ Dennis

46

PHP 5.5.0, DateTimeImmutable'ı tanıttı . bu sınıfın ekleme ve değiştirme yöntemleri yeni nesneler döndürür.

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

4
Maalesef a DateTimeile DateTimeImmutable. En azından IntlDateFormatter::formatObjectdeğişmezleri sevmeyenler var ( falsebiçimlendirilmiş dizge yerine döner ).
user276648

1
ah! Uzun zamandır hayalini kurmuş olmama rağmen, bir şekilde bunun var olduğunu hiç bilmiyordum. ve 5.5'te tamamen geri dönüyor ...
Ben

2
Bir çaylak gibi, nesnemi DateTimebir for döngüsünde değiştirerek nesne yönelimli bir tuzakla karşılaştım : D Bu sorunu güzelce çözdü ...
Wilt

3
@ user276648 Bu hata php 7.1.5'te
jontro

11

TLDR:

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

(Sığ kopya enaugh - Derin kopya-ing DateTime yapar (şu anda) hiçbir anlamda )

Bu kadar basit :)

"Php başka bir tarih saatinden datetime nesnesini oluştur" açıklaması:

  1. cloneAnahtar kelime düzenli hale sığ kopya - enaugh bu durum için (=> aşağıya bakınız neden)
  2. Bunu sarmak (), yeni oluşturulan nesneyi şu şekilde döndüren ifadeyi değerlendirir:clone
  3. ->modify() bu nedenle çağrılır ve yeni nesneyi değiştirir
  4. DateTime::modify(...) docs:

    Başarısızlık durumunda FALSE veya yöntem zincirleme için DateTime nesnesini döndürür.

  5. $date2artık $date1değişmeden kalırken yeni oluşturulan ve değiştirilmiş klon / kopyayı içerir

Neden burada derinlemesine kopyalamaya gerek yok:

Derin kopya / klon yalnızca referans olan özelliklerin hedeflerini kopyalamanız gerektiğinde gereklidir , ancak bu:

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();

çıktılar:

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

yani referans yok, sadece basit tipler => derin kopyaya gerek yok .


1

Eğer değişmelidir DateTimeToDateTimeImmutable

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

o zaman herhangi bir yöntemi DateTimedeğiştirmeden endişelenmeden çağırabilirsiniz


Bu gerçekten farklı bir sorunun cevabı.
Billy ONeal

Ben tamamen nasıl açıklanabilir sahip olabilir, Ama bu sorunun kaynağı olarak bu soruna bir çözüm @BillyONeal yöntemini çağırarak nasıl addüzerinde date2değeri değişiklikleri date1ve değerini kopyalamak için hiçbir yolu yoktur DateTimebir olmadıkça değişkenDateTimeImmutable
Hossein Shahdoost
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.