2013-12-19 2 views
0

Право это оказалось довольно сложным для объяснения, я создаю события календаря, которые имеют общие сведения, но в разные даты.PHP Clone Extended Object, DateTime Reference - это то же самое

Так что я делаю что-то вроде следующего, отмечают клон:

// Create event for each subject 
    $event = new CalendarEvent(); 
    $event->setTitle($subject->getTitle()); 

    // Add an event for every occurrence 
    // -- getDates() returns an array of DateTime objects 
    foreach($subject->getDates() as $date) { 
     $dateEvent = clone $event; 

     $dateEvent->setStartDate($date); 

     $events[] = $dateEvent; 
    } 

Однако если сбросить $events массив, мы можем видеть, что каждое событие дата начала указывает на то же ссылки:

Add:object(CalendarEvent)#2406 (5) { 
    ["startDateTime":"Event":private]=> 
    object(DateTime)#2411 (3) { 
    ["date"]=> 
    string(19) "2013-10-02 09:00:00" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
    } 
    ... trimmed ... 
} 
Add:object(CalendarEvent)#2413 (5) { 
    ["startDateTime":"Event":private]=> 
    object(DateTime)#2411 (3) { 
    ["date"]=> 
    string(19) "2013-10-16 09:00:00" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
    } 
    ... trimmed ... 
} 
Add:object(CalendarEvent)#2414 (5) { 
    ["startDateTime":"Event":private]=> 
    object(DateTime)#2411 (3) { 
    ["date"]=> 
    string(19) "2013-11-06 09:00:00" 
    ["timezone_type"]=> 
    int(3) 
    ["timezone"]=> 
    string(13) "Europe/Berlin" 
    } 
    ... trimmed ... 
} 

Каждые события startDateTime указывает на # 2411 это означает, что появляются все события, чтобы иметь то же самое время, даже несмотря на то, при условии, дата начала s разные.

Почему это происходит? Я думал, что копия создаст новую копию DateTime в памяти, на которую указывает.

Event->SetStartDate это просто следующий и в конструкторе я создаю новый DateTime для каждого события:

public function setStartDate(DateTime $date) { 
    $this->startDateTime->setDate($date->format('Y'), $date->format('m'), $date->format('d')); 
    } 

new CalendarEvent() Перемещение внутри цикла устраняет эту проблему, но я задаюсь вопросом, почему это происходит вообще? Почему все клонированные события указывают на тот же экземпляр DateTime?

ответ

1

РНР clone является НЕ рекурсивным, так что вы должны заменить

$dateEvent->setStartDate($date); 

с

$dateEvent->setStartDate(clone $date); 

Смотрите также документы: http://php.net/language.oop5.cloning

Когда объект клонированы, PHP 5 выполнит неглубокую копию всего свойств объекта. Любые свойства, которые являются ссылками на другие переменные , останутся ссылками.

Вот довольно грубая глубокая реализация клона:

/** 
* Implement PHP __clone to create a deep clone, not just a shallow copy. 
*/ 
public function __clone() { 
    foreach($this as $key => $val) { 
     if (is_object($val) || (is_array($val))) { 
      $this->{$key} = unserialize(serialize($val)); 
     } 
    } 
} 
+0

Я вижу, выглядит как я понял, как клон работает. Можно ли сделать глубокую копию? –

+1

Да, реализуя собственный волшебный метод '__clone' :) –

+0

Я предполагаю, что будет делать что-то вроде' $ this-> start = clone $ this-> start'? –

Смежные вопросы