是否可以实例化为子对象,然后在 PHP 中提取父对象?
Is it possible to instantiate as child object but then extract the parent object in PHP?
我 运行 遇到了一个解决 Zend Framework 1.x 限制的问题,目前我无法替换或更新它。我有一个新颖的想法,但我不确定是否可行。
基本问题是是否可以实例化扩展子对象,然后提取父对象进行序列化?
为了说明原因,本质上 Zend_Mail
class 对其方法有一些非常愚蠢的限制和类型检查,在我的例子中特别是 $mail->setType()
。
我的想法是,我可以创建一个扩展 class (My_Zend_Mail extends Zend_Mail
),然后覆盖 class 中的 setType() {...}
方法,消除限制,允许我在 Zend_Mail
class 中设置某些 protected
属性。限制是我需要将其作为序列化对象传递给远程服务器,并且远程服务器在反序列化时不会拥有或识别 My_Zend_Mail
class。所以我最后只需要序列化 Zend_Mail
父级。
所以回到最初的问题,我可以在通过扩展子对象实例化后提取父对象吗?
编辑: 我发现了以下问题,其选择的答案提出了一种骇人听闻的方式来重铸序列化字符串,以便将其反序列化为不同的对象....
Convert/cast an stdClass object to another class
这可能有效,但更进一步看起来有人也在通过反射 class 执行此操作,这更接近我正在寻找的东西。除非有其他建议,我可能会试一试并报告回来?
我能够通过使用稍微不同的搜索条件找到另一个答案,该搜索条件更多地处理 casting 而不是提取。最终为我工作的解决方案是基于反射 classes,我承认我只有一点经验,原始答案可以在这里找到:
我在这里复制代码以供后人使用,但这是直接复制的...
/**
* 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);
所以最终反射 class 使我们能够访问 Zend_Mail
中的受保护参数而无需扩展它。我本可以重写该方法以跳过我们扩展原始 class 以设置值的步骤,然后使用此方法对其进行转换,但像这样保留它更 OO 并且允许我使用这个方便在别处耍花招。
希望对您有所帮助!
我 运行 遇到了一个解决 Zend Framework 1.x 限制的问题,目前我无法替换或更新它。我有一个新颖的想法,但我不确定是否可行。
基本问题是是否可以实例化扩展子对象,然后提取父对象进行序列化?
为了说明原因,本质上 Zend_Mail
class 对其方法有一些非常愚蠢的限制和类型检查,在我的例子中特别是 $mail->setType()
。
我的想法是,我可以创建一个扩展 class (My_Zend_Mail extends Zend_Mail
),然后覆盖 class 中的 setType() {...}
方法,消除限制,允许我在 Zend_Mail
class 中设置某些 protected
属性。限制是我需要将其作为序列化对象传递给远程服务器,并且远程服务器在反序列化时不会拥有或识别 My_Zend_Mail
class。所以我最后只需要序列化 Zend_Mail
父级。
所以回到最初的问题,我可以在通过扩展子对象实例化后提取父对象吗?
编辑: 我发现了以下问题,其选择的答案提出了一种骇人听闻的方式来重铸序列化字符串,以便将其反序列化为不同的对象....
Convert/cast an stdClass object to another class
这可能有效,但更进一步看起来有人也在通过反射 class 执行此操作,这更接近我正在寻找的东西。除非有其他建议,我可能会试一试并报告回来?
我能够通过使用稍微不同的搜索条件找到另一个答案,该搜索条件更多地处理 casting 而不是提取。最终为我工作的解决方案是基于反射 classes,我承认我只有一点经验,原始答案可以在这里找到:
我在这里复制代码以供后人使用,但这是直接复制的...
/**
* 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);
所以最终反射 class 使我们能够访问 Zend_Mail
中的受保护参数而无需扩展它。我本可以重写该方法以跳过我们扩展原始 class 以设置值的步骤,然后使用此方法对其进行转换,但像这样保留它更 OO 并且允许我使用这个方便在别处耍花招。
希望对您有所帮助!