Объект глубокого клонирования PHP

Сценарий: извлеките шаблон электронной почты из базы данных и просмотрите список получателей, персонализировав электронную почту для каждого.

Мой шаблон электронной почты возвращается как вложенный объект. Это может выглядеть примерно так:

object(stdClass) {
    ["title"] => "Event Notification"
    ["sender"] => "[email protected]"
    ["content"] => object(stdClass) {
        ["salutation"] => "Dear %%firstname%%,"
        ["body"] => "Lorem ipsum %%recipient_email%% etc etc..."
    }
}

Затем я перебираю получателей, передавая этот объект $email функции personalise():

foreach( $recipients as $recipient ){
    $email_body = personalise( $email, $recipient );
    //send_email();
}

Проблема, конечно, в том, что мне нужно передать объект $email по ссылке, чтобы он заменил теги персонализации, но если я это сделаю, исходный объект изменится и больше не будет содержать теги персонализации.

Насколько я понимаю, клон мне здесь не поможет, потому что он создаст только поверхностную копию: объект содержимого внутри объекта электронной почты не будет клонирован.

Я читал об обходе этого с помощью unserialize(serialize($obj)) - но все, что я читал, говорит о том, что это большой удар по производительности.

Итак, два, наконец, добрались до моих двух вопросов:

  1. Является ли unserialize(serialize($obj)) разумным решением?
  2. Или я неправильно все это делаю? Есть ли другой способ создания персонализированных копий этого объекта электронной почты?

person Wintermute    schedule 31.05.2012    source источник
comment
Я считаю, что swiftmailer отлично справляется с тем, что вы пытаетесь сделать с плагином декоратора (swiftmailer.org/docs/plugins.html#decorator-plugin), плюс хорошо справляется с заголовками; мы получаем очень низкие результаты спама с этим.   -  person scott    schedule 31.05.2012


Ответы (2)


Вы можете добавить в свой класс электронной почты метод __clone(). Который автоматически вызывается, когда экземпляр этого класса клонируется с помощью clone(). В этом методе вы можете вручную добавить шаблон.

Пример:

class email {
    __clone() {
         $this->template = new template();
    }
}

.

unserialize(serialize($object)); // would be another solution...
person powtac    schedule 31.05.2012

Еще одно более универсальное и мощное решение: MyCLabs\DeepCopy.

Это помогает создавать глубокую копию без необходимости перегружать __clone (что может потребовать больших усилий, если у вас много разных объектов).

person Matthieu Napoli    schedule 04.06.2014
comment
Это правильный путь, особенно при использовании ORM (например, Doctrine2). - person Artur Bodera; 13.03.2015