我正在集成一个API到我的网站,它与存储在对象中的数据一起工作,而我的代码是使用数组编写的。

我想要一个快速和肮脏的函数将对象转换为数组。


当前回答

这是我的建议,如果你的对象中有私有成员的对象:

public function dismount($object) {
    $reflectionClass = new \ReflectionClass(get_class($object));
    $array = array();
    foreach ($reflectionClass->getProperties() as $property) {
        $property->setAccessible(true);
        if (is_object($property->getValue($object))) {
            $array[$property->getName()] = $this->dismount($property->getValue($object));
        } else {
            $array[$property->getName()] = $property->getValue($object);
        }
        $property->setAccessible(false);
    }
    return $array;
}

其他回答

Use:

function readObject($object) {
    $name = get_class ($object);
    $name = str_replace('\\', "\\\\", $name); // Outcomment this line, if you don't use
                                              // class namespaces approach in your project
    $raw = (array)$object;

    $attributes = array();
    foreach ($raw as $attr => $val) {
        $attributes[preg_replace('('.$name.'|\*|)', '', $attr)] = $val;
    }
    return $attributes;
}

它返回一个没有特殊字符和类名的数组。

我使用这个(需要递归解决适当的关键字):

    /**
     * This method returns the array corresponding to an object, including non public members.
     *
     * If the deep flag is true, is will operate recursively, otherwise (if false) just at the first level.
     *
     * @param object $obj
     * @param bool $deep = true
     * @return array
     * @throws \Exception
     */
    public static function objectToArray(object $obj, bool $deep = true)
    {
        $reflectionClass = new \ReflectionClass(get_class($obj));
        $array = [];
        foreach ($reflectionClass->getProperties() as $property) {
            $property->setAccessible(true);
            $val = $property->getValue($obj);
            if (true === $deep && is_object($val)) {
                $val = self::objectToArray($val);
            }
            $array[$property->getName()] = $val;
            $property->setAccessible(false);
        }
        return $array;
    }

用法示例,代码如下:

class AA{
    public $bb = null;
    protected $one = 11;

}

class BB{
    protected $two = 22;
}


$a = new AA();
$b = new BB();
$a->bb = $b;

var_dump($a)

将打印这个:

array(2) {
  ["bb"] => array(1) {
    ["two"] => int(22)
  }
  ["one"] => int(11)
}

您还可以使用Symfony Serializer组件

use Symfony\Component\Serializer\Encoder\JsonEncoder;
use Symfony\Component\Serializer\Normalizer\ObjectNormalizer;
use Symfony\Component\Serializer\Serializer;

$serializer = new Serializer([new ObjectNormalizer()], [new JsonEncoder()]);
$array = json_decode($serializer->serialize($object, 'json'), true);

这里发布的所有其他答案都只使用公共属性。下面是一个使用反射和getter处理类javabean对象的解决方案:

function entity2array($entity, $recursionDepth = 2) {
    $result = array();
    $class = new ReflectionClass(get_class($entity));
    foreach ($class->getMethods(ReflectionMethod::IS_PUBLIC) as $method) {
        $methodName = $method->name;
        if (strpos($methodName, "get") === 0 && strlen($methodName) > 3) {
            $propertyName = lcfirst(substr($methodName, 3));
            $value = $method->invoke($entity);

            if (is_object($value)) {
                if ($recursionDepth > 0) {
                    $result[$propertyName] = $this->entity2array($value, $recursionDepth - 1);
                }
                else {
                    $result[$propertyName] = "***";  // Stop recursion
                }
            }
            else {
                $result[$propertyName] = $value;
            }
        }
    }
    return $result;
}

只是对它进行类型转换

$array = (array) $yourObject;

从数组:

如果将一个对象转换为数组,则结果是一个数组,其元素是该对象的属性。键是成员变量名,但有几个明显的例外:整数属性不可访问;私有变量的类名在变量名之前;受保护变量的变量名前面有一个'*'。这些前置值的两边都是空字节。

示例:简单对象

$object = new StdClass;
$object->foo = 1;
$object->bar = 2;

var_dump( (array) $object );

输出:

array(2) {
  'foo' => int(1)
  'bar' => int(2)
}

示例:复杂对象

class Foo
{
    private $foo;
    protected $bar;
    public $baz;

    public function __construct()
    {
        $this->foo = 1;
        $this->bar = 2;
        $this->baz = new StdClass;
    }
}

var_dump( (array) new Foo );

输出(为清晰起见,编辑了\0s):

array(3) {
  '\0Foo\0foo' => int(1)
  '\0*\0bar' => int(2)
  'baz' => class stdClass#2 (0) {}
}

输出var_export而不是var_dump:

array (
  '' . "\0" . 'Foo' . "\0" . 'foo' => 1,
  '' . "\0" . '*' . "\0" . 'bar' => 2,
  'baz' =>
  stdClass::__set_state(array(
  )),
)

以这种方式进行类型转换不会对对象图进行深度转换,您需要应用null字节(如手册引用中所解释的那样)来访问任何非公共属性。因此,当强制转换StdClass对象或只有公共属性的对象时,这种方法效果最好。快速和肮脏(你所要求的)是可以的。

也可以看看这篇深入的博客文章:

快速PHP对象到数组的转换