是否可以实例化为子对象,然后在PHP中提取父对象? [英] Is it possible to instantiate as child object but then extract the parent object in PHP?

查看:209
本文介绍了是否可以实例化为子对象,然后在PHP中提取父对象?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在解决Zend Framework 1.x中的限制时遇到问题,目前无法替换或更新它.我有一个新主意,但不确定是否可行.

基本问题是是否可以实例化扩展的子对象,但随后可以提取父对象以进行序列化?

为了说明为什么,本质上Zend_Mail类实际上有一些愚蠢的限制,并且对其方法进行类型检查,在我的情况下,具体来说是$mail->setType().

我的想法是,我可以创建一个扩展类(My_Zend_Mail extends Zend_Mail),然后在我的类中重写setType() {...}方法,消除限制,使我可以在Zend_Mail类中设置某些protected属性.限制是我需要将它作为序列化的对象传递给远程服务器,并且该远程服务器在未序列化时将不具有或识别My_Zend_Mail类.所以我只需要在序列末尾对Zend_Mail父级进行序列化.

回到最初的问题,在通过扩展子对象实例化父对象之后,我可以提取父对象吗?


我发现了以下问题,该问题的选定答案提出了一种怪异的方法来重铸序列化的字符串,以便将其反序列化为其他对象....

将stdClass对象转换/投射到另一个类

这可能行得通,尽管看上去更像是有人也在通过Reflection类执行此操作,它与我正在寻找的内容更接近.除非有其他建议,否则我可以试一下并提出报告?

解决方案

我能够通过使用略微不同的搜索条件来找到另一个答案,而搜索条件与提取相比,对广播的处理更多.最终为我工作的解决方案基于我承认只有很少经验的反射类,可以在此处找到原始答案:

https://stackoverflow.com/a/9812059/1058733

我在这里复制后代的代码,但这是直接复制的...

/**
 * 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中的受保护参数,而不必对其进行扩展.我本来可以重写该方法,以跳过我们要扩展原始类以设置值的步骤,然后使用此方法进行强制转换,但是像这样将其保留为更多对象,并允许我在其他地方使用此方便的技巧. /p>

希望有帮助!

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?

解决方案

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://stackoverflow.com/a/9812059/1058733

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!

这篇关于是否可以实例化为子对象,然后在PHP中提取父对象?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆