将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; } } }