Можно ли создать экземпляр как дочерний объект, а затем извлечь родительский объект в PHP?

У меня проблема с ограничениями в Zend Framework 1.x, и я не могу ее заменить или обновить на данный момент. У меня есть новая идея, но я не уверен, что это возможно.

Основной вопрос: Возможно ли создать экземпляр расширенного дочернего объекта, но потом извлечь родительский объект для сериализации?

Чтобы проиллюстрировать, почему, по существу, класс Zend_Mail имеет некоторые действительно глупые ограничения и проверки типов своих методов, в моем случае конкретно $mail->setType().

Моя мысль заключается в том, что я могу создать расширяемый класс (My_Zend_Mail extends Zend_Mail), а затем переопределить метод setType() {...} в моем классе, исключив ограничения, позволив мне установить определенные свойства protected в классе Zend_Mail. Ограничение заключается в том, что мне нужно передать это удалённому серверу в виде сериализованного объекта, и этот удаленный сервер НЕ будет иметь или распознать класс My_Zend_Mail, когда он будет неэтериализован. Поэтому мне нужно сериализовать только родителя Zend_Mail на моем конце.

Итак, вернемся к исходному вопросу, могу ли я извлечь родительский объект после того, как он был создан через дочерний объект?


РЕДАКТИРОВАТЬ: Я нашел следующий вопрос, чей выбранный ответ предлагает хакерский способ переделать сериализованную строку, чтобы она не была инициализирована как другой объект....

Преобразование/литье объекта stdClass в другой класс

Это может сработать, хотя и дальше, похоже, кто-то делает это через класс Reflection, что ближе к тому, что я ищу. Я могу сказать, что выстрел и отчет, если нет других предложений?

Ответ 1

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

fooobar.com/info/14778/...

Я дублирую код для потомков здесь, но это было скопировано прямо...

/**
 * Class casting
 *
 * @param string|object $destination
 * @param object $sourceObject
 * @return object
 */
function cast($destination, $sourceObject)
{
    if (is_string($destination)) {
        $destination = new $destination();
    }
    $sourceReflection = new ReflectionObject($sourceObject);
    $destinationReflection = new ReflectionObject($destination);
    $sourceProperties = $sourceReflection->getProperties();
    foreach ($sourceProperties as $sourceProperty) {
        $sourceProperty->setAccessible(true);
        $name = $sourceProperty->getName();
        $value = $sourceProperty->getValue($sourceObject);
        if ($destinationReflection->hasProperty($name)) {
            $propDest = $destinationReflection->getProperty($name);
            $propDest->setAccessible(true);
            $propDest->setValue($destination,$value);
        } else {
            $destination->$name = $value;
        }
    }
    return $destination;
}

И пример использования был проиллюстрирован так...

class A {
  private $_x;   
}

class B {
  public $_x;   
}

$a = new A();
$b = new B();

$x = cast('A',$b);
$x = cast('B',$a);

Итак, в конце класс отражения дает нам возможность доступа к защищенным параметрам в Zend_Mail без необходимости его расширения. Я мог бы переписать метод, чтобы пропустить шаг, на котором мы ДОБАВЛЯЕМ исходный класс, чтобы установить значения, а затем использовать этот метод для его броска, но оставляя его таким образом, как это больше OO, и позволяет мне использовать этот удобный трюк в другом месте.

Надеюсь, что это поможет!