Is it possible to instantiate as child object but then extract the parent object in PHP?
Asked Answered
J

1

0

I'm running into a problem working around limitations in Zend Framework 1.x and I can't replace or update it at the moment. I have a novel idea but I'm not sure if it's possible.

The basic question is Is it possible to instantiate an extending child object, but then extract the parent object afterward for serialization?

To illustrate why, essentially the Zend_Mail class has some really stupid limitations and type checks on its methods, in my case specifically $mail->setType().

My thought is that I can create an extending class (My_Zend_Mail extends Zend_Mail), then override the setType() {...} method in my class, eliminating the restrictions, allowing me to set certain protected properties in the Zend_Mail class. The limitation is that I need to hand this off to a remote server as a serialized object, and that remote server will NOT have or recognize the My_Zend_Mail class when it's unserialized. So I need to serialize only the Zend_Mail parent at my end.

So back to the original question, can I extract a parent object, after it's been instantiated via an extending child?


EDIT: I've found the following question whose selected answer proposes a hackish way to recast a serialized string so that it unserializes as a different object....

Convert/cast an stdClass object to another class

This might work, though further down it looks like someone is doing this via the Reflection class as well, which is closer to what I'm looking for. I might give that a shot and report back, unless there are other suggestions?

Jinks answered 11/2, 2016 at 21:39 Comment(4)
Sorry, I don't think you can. To get the parent object you need to instantiate the parent class. However from the child object you should have access to parent methods and properties by using "parent::example()" for example to call parent "example" method.Parnell
Sorry @CatalinCislariu, but it's obvious that I'd have access to the parent properties and methods... which is why I proposed it. As far as being able to re-cast or extract the parent, can you reference anything at all that leads you to that conclusion?Jinks
I was wrong, look at the bottom.Parnell
@CatalinCislariu Yes, I put that there, this is my question?!?! Anyhow, the reflection class solution worked, and I've invited that user to answer here.Jinks
J
0

I was able to find another answer by using slightly different search criteria dealing more with casting than extracting. The solution that ended up working for me was based on the reflection classes which I admitedly have only a little experience with, the original answer is found here:

https://mcmap.net/q/54344/-convert-cast-an-stdclass-object-to-another-class

I'm duplicating the code for posterity here, but this was directly copied...

/**
 * 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;
}

And the example usage was illustrated like so...

class A {
  private $_x;   
}

class B {
  public $_x;   
}

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

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

So in the end the reflection class is giving us the ability to access the protected parameters within Zend_Mail without having to extend it. I could have rewritten the method to skip the step where we DO extend the original class to set the values, and then use this method to cast it, but leaving it like this is more OO and allows me to use this convenient trick elsewhere.

Hope that helps!

Jinks answered 16/2, 2016 at 14:44 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.