Php 将stdClass对象转换/强制转换为另一个类

Php 将stdClass对象转换/强制转换为另一个类,php,stdclass,Php,Stdclass,我使用的是第三方存储系统,它只返回stdClass对象,无论出于某种模糊的原因输入了什么。因此,我很想知道是否有办法将stdClass对象强制转换为给定类型的完整对象 例如: //$stdClass is an stdClass instance $converted = (BusinessClass) $stdClass; 我只是将stdClass转换成一个数组,并将其提供给BusinessClass构造函数,但也许有一种方法可以恢复我不知道的初始类 注意:我对“更改您的存储系统”类型的答案

我使用的是第三方存储系统,它只返回stdClass对象,无论出于某种模糊的原因输入了什么。因此,我很想知道是否有办法将stdClass对象强制转换为给定类型的完整对象

例如:

//$stdClass is an stdClass instance
$converted = (BusinessClass) $stdClass;
我只是将stdClass转换成一个数组,并将其提供给BusinessClass构造函数,但也许有一种方法可以恢复我不知道的初始类

注意:我对“更改您的存储系统”类型的答案不感兴趣,因为这不是我感兴趣的问题。请认为这是一个关于语言能力的学术问题。

干杯

请参见可能的演员阵容

允许的演员阵容包括:

  • (int),(整数)-强制转换为整数
  • (布尔),(布尔)-强制转换为布尔
  • (浮动),(双重),(实际)-转换为浮动
  • (字符串)-转换为字符串
  • (阵列)-强制转换为阵列
  • (对象)-强制转换到对象
  • (未设置)-强制转换为NULL(PHP5)
您将不得不执行从stdClass到另一个具体类的转换。应该不会太难做到

或者,如果您心情不好,可以修改以下代码:

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), '"'), ':')
    ));
}

要将
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

这是有限的,因为新的运算符不知道需要哪些参数。对于您的情况,可能是合适的。

您可以使用上述函数强制转换不相似的类对象(PHP>=5.3)

例如:

class A 
{
  private $_x;   
}

class B 
{
  public $_x;   
}

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

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

我有一个非常类似的问题。简化反射解决方案对我来说效果很好:

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

更改了深熔铸的函数(使用递归)


希望有人觉得这个有用

//stdClass对象的新实例
$item=(对象)数组(
'id'=>1,
'值'=>'测试对象',
);
//通过传递将stdClass对象强制转换为其他类型
//通过构造函数创建的值
$casted=新的ModelFoo($item);
//或者。。
//使用方法强制转换stdObject
$casted=新的ModelFoo;
$casted->cast($item);
级浇注料
{
公共函数构造($object=null)
{
$this->cast($object);
}
公共函数强制转换($object)
{
if(is_数组($object)| is_对象($object)){
foreach($key=>$value的对象){
$this->$key=$value;
}
}
}
} 
class ModelFoo扩展了可浇铸材料
{
公费$id;
公帑价值;;
}

顺便说一句:如果序列化,转换非常重要,主要是因为反序列化会破坏对象的类型,并转化为stdclass,包括DateTime对象

我更新了@Jadrovski的示例,现在它允许对象和数组

范例

$stdobj=new StdClass();
$stdobj->field=20;
$obj=new SomeClass();
fixCast($obj,$stdobj);
示例数组

$stdobjArr=array(new StdClass(),new StdClass());
$obj=array(); 
$obj[0]=new SomeClass(); // at least the first object should indicates the right class.
fixCast($obj,$stdobj);
代码:(它是递归的)。但是,我不知道它是否与数组一起递归。可能是它缺少一个额外的is_数组

public static function fixCast(&$destination,$source)
{
    if (is_array($source)) {
        $getClass=get_class($destination[0]);
        $array=array();
        foreach($source as $sourceItem) {
            $obj = new $getClass();
            fixCast($obj,$sourceItem);
            $array[]=$obj;
        }
        $destination=$array;
    } else {
        $sourceReflection = new \ReflectionObject($source);
        $sourceProperties = $sourceReflection->getProperties();
        foreach ($sourceProperties as $sourceProperty) {
            $name = $sourceProperty->getName();
            if (is_object(@$destination->{$name})) {
                fixCast($destination->{$name}, $source->$name);
            } else {
                $destination->{$name} = $source->$name;
            }
        }
    }
}

考虑向BusinessClass添加一个新方法:

public static function fromStdClass(\stdClass $in): BusinessClass
{
  $out                   = new self();
  $reflection_object     = new \ReflectionObject($in);
  $reflection_properties = $reflection_object->getProperties();
  foreach ($reflection_properties as $reflection_property)
  {
    $name = $reflection_property->getName();
    if (property_exists('BusinessClass', $name))
    {
      $out->{$name} = $in->$name;
    }
  }
  return $out;
}
然后,您可以从$stdClass创建一个新的BusinessClass:

$converted = BusinessClass::fromStdClass($stdClass);
还有另一种方法

由于最新的PHP7版本,现在可以实现以下功能

$theStdClass=(对象)[
“a'=>“Alpha”,
“b”=>“好极了”,
“c”=>“查理”,
'd'=>'Delta',
];
$foo=新类($theStdClass){
公共函数构造($data){
如果(!is_数组($data)){
$data=(数组)$data;
}
foreach($prop=>$value形式的数据){
$this->{$prop}=$value;
}
}
公共函数word4Letter($letter){
返回$this->{$letter};
}
};
打印$foo->word4Letter('a')。PHP_EOL;//阿尔法
打印$foo->word4Letter('b')。PHP_EOL;//布拉沃河
打印$foo->word4Letter('c')。PHP_EOL;//查理
打印$foo->word4Letter('d')。PHP_EOL;//三角洲
打印$foo->word4Letter('e')。PHP_EOL;//PHP注意事项:未定义属性
在本例中,$foo被初始化为一个匿名类,该类将一个数组或stdClass作为构造函数的唯一参数

最后,我们循环遍历传递对象中包含的每个项,然后动态地分配给对象的属性


为了使此approch事件更通用,您可以编写一个接口或特性,您将在希望能够强制转换stdClass的任何类中实现它。

还有另一种使用decorator模式和PHPs magic getter&Setter的方法:

// A simple StdClass object    
$stdclass = new StdClass();
$stdclass->foo = 'bar';

// Decorator base class to inherit from
class Decorator {

    protected $object = NULL;

    public function __construct($object)
    {
       $this->object = $object;  
    }

    public function __get($property_name)
    {
        return $this->object->$property_name;   
    }

    public function __set($property_name, $value)
    {
        $this->object->$property_name = $value;   
    }
}

class MyClass extends Decorator {}

$myclass = new MyClass($stdclass)

// Use the decorated object in any type-hinted function/method
function test(MyClass $object) {
    echo $object->foo . '<br>';
    $object->foo = 'baz';
    echo $object->foo;   
}

test($myclass);
//一个简单的StdClass对象
$stdclass=新stdclass();
$stdclass->foo='bar';
//要从中继承的装饰器基类
班级装饰员{
受保护的$object=NULL;
公共函数构造($object)
{
$this->object=$object;
}
公共函数获取($property\u name)
{
返回$this->object->$property\u name;
}
公共函数集($property\u name,$value)
{
$this->object->$property\u name=$value;
}
}
类MyClass扩展了Decorator{}
$myclass=新的myclass($stdclass)
//在任何类型的提示函数/方法中使用装饰对象
功能测试(MyClass$对象){
echo$object->foo.“
”; $object->foo='baz'; echo$object->foo; } 测试(myclass);
将其转换为数组,返回该数组的第一个元素,并将返回参数设置为该类。现在您应该获得该类的自动完成,因为它将把它重新注册为该类而不是stdclass

/**
 * @return Order
 */
    public function test(){
    $db = new Database();

    $order = array();
    $result = $db->getConnection()->query("select * from `order` where productId in (select id from product where name = 'RTX 2070')");
    $data = $result->fetch_object("Order"); //returns stdClass
    array_push($order, $data);

    $db->close();
    return $order[0];
}

这是一种聪明的技术。不会使用它,因为我目前解决这个问题的方法更稳定,但仍然很有趣。您最终会得到一个
\uuuphp\ucomplete\u类// A simple StdClass object    
$stdclass = new StdClass();
$stdclass->foo = 'bar';

// Decorator base class to inherit from
class Decorator {

    protected $object = NULL;

    public function __construct($object)
    {
       $this->object = $object;  
    }

    public function __get($property_name)
    {
        return $this->object->$property_name;   
    }

    public function __set($property_name, $value)
    {
        $this->object->$property_name = $value;   
    }
}

class MyClass extends Decorator {}

$myclass = new MyClass($stdclass)

// Use the decorated object in any type-hinted function/method
function test(MyClass $object) {
    echo $object->foo . '<br>';
    $object->foo = 'baz';
    echo $object->foo;   
}

test($myclass);
/**
 * @return Order
 */
    public function test(){
    $db = new Database();

    $order = array();
    $result = $db->getConnection()->query("select * from `order` where productId in (select id from product where name = 'RTX 2070')");
    $data = $result->fetch_object("Order"); //returns stdClass
    array_push($order, $data);

    $db->close();
    return $order[0];
}