将stdClass对象转换/转换为另一个类
我正在使用第三方存储系统,只是返回stdClass对象,无论我input什么因为一些晦涩的原因。 所以我很想知道是否有一种方法来将stdClass对象强制转换为给定types的完整对象。
比如说:
//$stdClass is an stdClass instance $converted = (BusinessClass) $stdClass;
我只是将stdClass强制转换为数组,并将其提供给BusinessClass构造函数,但也许有办法恢复我不知道的初始类。
注意:我对“更改存储系统”types的答案不感兴趣,因为它不是兴趣点。 请把它看作是一门关于语言能力的学术问题。
干杯
请参阅可能的演员的types杂耍手册 。
允许的演员是:
- (int),(整数) – 转换为整数
- (布尔),(布尔) – 转换为布尔值
- (浮动),(双),(真实) – 投到浮动
- (string) – 强制转换为string
- (数组) – 转换为数组
- (对象) – 投到对象
- (未设置) – 转换为NULL(PHP 5)
你将不得不写一个从stdClass转换到另一个具体类的Mapper 。 不应该太难做。
或者,如果你的心情不好,你可以修改下面的代码:
function arrayToObject(array $array, $className) { return unserialize(sprintf( 'O:%d:"%s"%s', strlen($className), $className, strstr(serialize($array), ':') )); }
它将一个数组伪造成一个特定类的对象。 这是通过首先序列化数组,然后更改序列化的数据,以便它表示某个类。 然后将结果反序列化为这个类的一个实例。 但是就像我说的那样,这是骇人的,所以期待副作用。
对于对象来说,代码将是
function objectToObject($instance, $className) { return unserialize(sprintf( 'O:%d:"%s"%s', strlen($className), $className, strstr(strstr(serialize($instance), '"'), ':') )); }
你可以使用上面的函数来转换不类似的类对象(PHP> = 5.3)
/** * 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);
将stdClass
所有现有属性移动到指定类名称的新对象中:
/** * recast stdClass object to an object with type * * @param string $className * @param stdClass $object * @throws InvalidArgumentException * @return mixed new, typed object */ function recast($className, stdClass &$object) { if (!class_exists($className)) throw new InvalidArgumentException(sprintf('Inexistant class %s.', $className)); $new = new $className(); foreach($object as $property => &$value) { $new->$property = &$value; unset($object->$property); } unset($value); $object = (unset) $object; return $new; }
用法:
$array = array('h','n'); $obj=new stdClass; $obj->action='auth'; $obj->params= &$array; $obj->authKey=md5('i'); class RestQuery{ public $action; public $params=array(); public $authKey=''; } $restQuery = recast('RestQuery', $obj); var_dump($restQuery, $obj);
输出:
object(RestQuery)#2 (3) { ["action"]=> string(4) "auth" ["params"]=> &array(2) { [0]=> string(1) "h" [1]=> string(1) "n" } ["authKey"]=> string(32) "865c0c0b4ab0e063e5caa3387c1a8741" } NULL
这是有限的,因为new
运营商,因为它是未知哪些参数将需要。 对于你的情况可能适合。
我有一个非常类似的问题。 简化reflection解决scheme对我来说工作得很好:
public static function cast($destination, \stdClass $source) { $sourceReflection = new \ReflectionObject($source); $sourceProperties = $sourceReflection->getProperties(); foreach ($sourceProperties as $sourceProperty) { $name = $sourceProperty->getName(); $destination->{$name} = $source->$name; } return $destination; }
希望有人觉得这有用
// new instance of stdClass Object $item = (object) array( 'id' => 1, 'value' => 'test object', ); // cast the stdClass Object to another type by passing // the value through constructor $casted = new ModelFoo($item); // OR.. // cast the stdObject using the method $casted = new ModelFoo; $casted->cast($item);
class Castable { public function __construct($object = null) { $this->cast($object); } public function cast($object) { if (is_array($object) || is_object($object)) { foreach ($object as $key => $value) { $this->$key = $value; } } } }
class ModelFoo extends Castable { public $id; public $value; }
改变深度铸造的function(使用recursion)
/** * Translates type * @param $destination Object destination * @param stdClass $source Source */ private static function Cast(&$destination, stdClass $source) { $sourceReflection = new \ReflectionObject($source); $sourceProperties = $sourceReflection->getProperties(); foreach ($sourceProperties as $sourceProperty) { $name = $sourceProperty->getName(); if (gettype($destination->{$name}) == "object") { self::Cast($destination->{$name}, $source->$name); } else { $destination->{$name} = $source->$name; } } }