我正在将API集成到我的网站,该网站使用存储在对象中的数据,而我的代码是使用数组编写的。
我想要一个快速而又脏的函数将对象转换为数组。
答案 0 :(得分:1246)
只是强调它
$array = (array) $yourObject;
来自http://www.php.net/manual/en/language.types.array.php
如果将对象转换为数组,则结果是一个数组,其元素是对象的属性。键是成员变量名,有一些值得注意的例外:整数属性是不可访问的;私有变量的类名前置于变量名;受保护的变量在变量名前面加上'*'。这些前置值在任一侧都有空字节。
示例:简单对象
$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(
)),
)
以这种方式进行类型转换不会对对象图进行深度转换,您需要应用空字节(如手册中所述)来访问任何非公共属性。因此,在仅使用公共属性转换StdClass对象或对象时,这种方法效果最佳。为了快速和肮脏(你要求的),没关系。
另见这篇深入的博客文章:
答案 1 :(得分:294)
您可以依靠JSON编码/解码函数的行为快速将深层嵌套对象转换为关联数组:
$array = json_decode(json_encode($nested_object), true);
答案 2 :(得分:63)
从第一次Google搜索“ php对象到关联数组”,我们有了这个:
function object_to_array($data)
{
if (is_array($data) || is_object($data))
{
$result = array();
foreach ($data as $key => $value)
{
$result[$key] = object_to_array($value);
}
return $result;
}
return $data;
}
答案 3 :(得分:51)
如果你的对象属性是公开的,你可以这样做:
$array = (array) $object;
如果它们是私有的或受保护的,它们将在阵列上具有奇怪的键名。因此,在这种情况下,您将需要以下功能:
function dismount($object) {
$reflectionClass = new ReflectionClass(get_class($object));
$array = array();
foreach ($reflectionClass->getProperties() as $property) {
$property->setAccessible(true);
$array[$property->getName()] = $property->getValue($object);
$property->setAccessible(false);
}
return $array;
}
答案 4 :(得分:12)
class Test{
const A = 1;
public $b = 'two';
private $c = test::A;
public function __toArray(){
return call_user_func('get_object_vars', $this);
}
}
$my_test = new Test();
var_dump((array)$my_test);
var_dump($my_test->__toArray());
<强>输出强>
array(2) {
["b"]=>
string(3) "two"
["Testc"]=>
int(1)
}
array(1) {
["b"]=>
string(3) "two"
}
答案 5 :(得分:10)
此处发布的所有其他答案仅适用于公共属性。这是一个使用反射和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;
}
答案 6 :(得分:9)
以下是一些代码:
function object_to_array($data) {
if ((! is_array($data)) and (! is_object($data))) return 'xxx'; //$data;
$result = array();
$data = (array) $data;
foreach ($data as $key => $value) {
if (is_object($value)) $value = (array) $value;
if (is_array($value))
$result[$key] = object_to_array($value);
else
$result[$key] = $value;
}
return $result;
}
答案 7 :(得分:8)
get_object_vars($obj)
怎么样?如果您只想访问对象的公共属性,似乎很有用。
http://www.php.net/function.get-object-vars
答案 8 :(得分:6)
键入将对象转换为数组。
$arr = (array) $Obj;
它将解决您的问题。
答案 9 :(得分:6)
您可以轻松使用此功能获得结果。
function objetToArray($adminBar){
$reflector = new ReflectionObject($adminBar);
$nodes = $reflector->getProperties();
$out=[];
foreach ($nodes as $node) {
$nod=$reflector->getProperty($node->getName());
$nod->setAccessible(true);
$out[$node->getName()]=$nod->getValue($adminBar);
}
return $out;
}
使用&gt; = php5
答案 10 :(得分:5)
将对象转换为数组只需显式转换
$name_of_array = (array) $name_of_object;
答案 11 :(得分:5)
您还可以在PHP中创建函数来转换对象数组。
function object_to_array($object) {
return (array) $object;
}
答案 12 :(得分:5)
您好,
这是我将PHP对象转换为关联数组的递归PHP函数
// ---------------------------------------------------------
// ----- object_to_array_recusive --- function (PHP) -------
// ---------------------------------------------------------
// --- arg1: -- $object = PHP Object - required ---
// --- arg2: -- $assoc = TRUE or FALSE - optional ---
// --- arg3: -- $empty = '' (Empty String) - optional ---
// ---------------------------------------------------------
// ----- return: Array from Object --- (associative) -------
// ---------------------------------------------------------
function object_to_array_recusive ( $object, $assoc=TRUE, $empty='' )
{
$res_arr = array();
if (!empty($object)) {
$arrObj = is_object($object) ? get_object_vars($object) : $object;
$i=0;
foreach ($arrObj as $key => $val) {
$akey = ($assoc !== FALSE) ? $key : $i;
if (is_array($val) || is_object($val)) {
$res_arr[$akey] = (empty($val)) ? $empty : object_to_array_recusive($val);
}
else {
$res_arr[$akey] = (empty($val)) ? $empty : (string)$val;
}
$i++;
}
}
return $res_arr;
}
// ---------------------------------------------------------
// ---------------------------------------------------------
用法示例:
// ---- return associative array from object, ... use:
$new_arr1 = object_to_array_recusive($my_object);
// -- or --
// $new_arr1 = object_to_array_recusive($my_object,TRUE);
// -- or --
// $new_arr1 = object_to_array_recusive($my_object,1);
// ---- return numeric array from object, ... use:
$new_arr2 = object_to_array_recusive($my_object,FALSE);
答案 13 :(得分:4)
将stdClass转换为数组的自定义函数:
function objectToArray($d) {
if (is_object($d)) {
// Gets the properties of the given object
// with get_object_vars function
$d = get_object_vars($d);
}
if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return array_map(__FUNCTION__, $d);
} else {
// Return array
return $d;
}
}
另一个将Array转换为stdClass的自定义函数:
function arrayToObject($d) {
if (is_array($d)) {
/*
* Return array converted to object
* Using __FUNCTION__ (Magic constant)
* for recursive call
*/
return (object) array_map(__FUNCTION__, $d);
} else {
// Return object
return $d;
}
}
用法示例:
// Create new stdClass Object
$init = new stdClass;
// Add some test data
$init->foo = "Test data";
$init->bar = new stdClass;
$init->bar->baaz = "Testing";
$init->bar->fooz = new stdClass;
$init->bar->fooz->baz = "Testing again";
$init->foox = "Just test";
// Convert array to object and then object back to array
$array = objectToArray($init);
$object = arrayToObject($array);
// Print objects and array
print_r($init);
echo "\n";
print_r($array);
echo "\n";
print_r($object);
答案 14 :(得分:4)
首先,如果你需要一个来自对象的数组,你可能应该首先将数据构成数组。想一想。
不要使用foreach语句或JSON转换。如果您正在计划这个,那么您再次使用数据结构,而不是使用对象。
如果您确实需要它,请使用面向对象的方法来获得干净且可维护的代码。例如:
对象为数组
class PersonArray implements \ArrayAccess, \IteratorAggregate
{
public function __construct(Person $person) {
$this->person = $person;
}
// ...
}
如果您需要所有属性,请使用传输对象
class PersonTransferObject
{
private $person;
public function __construct(Person $person) {
$this->person = $person;
}
public function toArray() {
return [
// 'name' => $this->person->getName();
];
}
}
答案 15 :(得分:3)
转换和删除讨厌的星星:
$array = (array) $object;
foreach($array as $key => $val)
{
$new_array[str_replace('*_','',$key)] = $val;
}
可能比使用反射更便宜。
答案 16 :(得分:3)
当您从数据库中获取数据作为对象时,您可能希望这样做 - &gt;
// Suppose result is the end product from some query $query
$result = $mysqli->query($query);
$result = db_result_to_array($result);
function db_result_to_array($result)
{
$res_array = array();
for ($count=0; $row = $result->fetch_assoc(); $count++)
$res_array[$count] = $row;
return $res_array;
}
答案 17 :(得分:3)
您也可以使用The Symfony Serializer Component
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);
答案 18 :(得分:3)
&#34; well-knwon&#34;代码
/*** mixed Obj2Array(mixed Obj)***************************************/
static public function Obj2Array($_Obj) {
if (is_object($_Obj))
$_Obj = get_object_vars($_Obj);
return(is_array($_Obj) ? array_map(__METHOD__, $_Obj) : $_Obj);
} // BW_Conv::Obj2Array
请注意,如果该函数是类的成员(如上所述),则必须将__FUNCTION__
更改为__METHOD__
答案 19 :(得分:3)
function readObject($object) {
$name = get_class ($object);
$name = str_replace('\\', "\\\\", $name); \\ Comment this line, if you dont 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;
}
返回没有特殊字符和类名的数组
答案 20 :(得分:2)
这个答案只是这篇文章的不同答案的结合,但它是用关联数组中的简单值或数组转换具有公共或私有属性的PHP对象的解决方案......
function object_to_array($obj)
{
if (is_object($obj)) $obj = (array)$this->dismount($obj);
if (is_array($obj)) {
$new = array();
foreach ($obj as $key => $val) {
$new[$key] = $this->object_to_array($val);
}
} else $new = $obj;
return $new;
}
function dismount($object)
{
$reflectionClass = new \ReflectionClass(get_class($object));
$array = array();
foreach ($reflectionClass->getProperties() as $property) {
$property->setAccessible(true);
$array[$property->getName()] = $property->getValue($object);
$property->setAccessible(false);
}
return $array;
}
答案 21 :(得分:2)
@ SpYk3HH的简短解决方案
function objectToArray($o)
{
$a = array();
foreach ($o as $k => $v)
$a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v;
return $a;
}
答案 22 :(得分:2)
对于您而言,如果使用“装饰器”或“日期模型转换”模式,则是正确/美丽的。例如:
您的模型
class Car {
/** @var int */
private $color;
/** @var string */
private $model;
/** @var string */
private $type;
/**
* @return int
*/
public function getColor(): int
{
return $this->color;
}
/**
* @param int $color
* @return Car
*/
public function setColor(int $color): Car
{
$this->color = $color;
return $this;
}
/**
* @return string
*/
public function getModel(): string
{
return $this->model;
}
/**
* @param string $model
* @return Car
*/
public function setModel(string $model): Car
{
$this->model = $model;
return $this;
}
/**
* @return string
*/
public function getType(): string
{
return $this->type;
}
/**
* @param string $type
* @return Car
*/
public function setType(string $type): Car
{
$this->type = $type;
return $this;
}
}
装饰器
class CarArrayDecorator
{
/** @var Car */
private $car;
/**
* CarArrayDecorator constructor.
* @param Car $car
*/
public function __construct(Car $car)
{
$this->car = $car;
}
/**
* @return array
*/
public function getArray(): array
{
return [
'color' => $this->car->getColor(),
'type' => $this->car->getType(),
'model' => $this->car->getModel(),
];
}
}
用法
$car = new Car();
$car->setType('type#');
$car->setModel('model#1');
$car->setColor(255);
$carDecorator = new CarArrayDecorator($car);
$carResponseData = $carDecorator->getArray();
这样,它将使代码更美观,更正确。
答案 23 :(得分:1)
由于很多人因动态访问对象属性而遇到此线程,我只想指出你可以在php中执行此操作:$valueRow->{"valueName"}
在Context中(为了便于阅读,删除了HTML输出):
$valueRows = json_decode("{...}"); // rows of unordered values decoded from a json-object
foreach($valueRows as $valueRow){
foreach($references as $reference){
if(isset($valueRow->{$reference->valueName})){
$tableHtml .= $valueRow->{$reference->valueName};
}else{
$tableHtml .= " ";
}
}
}
答案 24 :(得分:1)
通过使用类型转换,您可以解决您的问题。 只需在返回对象中添加以下行:
$arrObj = array(yourReturnedObject);
您还可以使用以下方法为其添加新的键和值对:
$arrObj['key'] = value;
答案 25 :(得分:1)
我的建议是,如果你的对象中有私人成员的对象:
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;
}
答案 26 :(得分:0)
出于单元Testig的目的,我建议改用json_decode(json_encode($object), true)
。
因为如果您尝试对复杂对象(例如以下对象)使用(array) $obj
,则单元测试将失败。考虑以下测试案例:
希望这对某人有帮助!
答案 27 :(得分:0)
我使用这个(需要具有正确密钥的递归解决方案):
/**
* 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)
}
答案 28 :(得分:0)
不是新的解决方案,但包括可用的toArray方法转换
function objectToArray($r)
{
if (is_object($r)) {
if (method_exists($r, 'toArray')) {
return $r->toArray(); // returns result directly
} else {
$r = get_object_vars($r);
}
}
if (is_array($r)) {
$r = array_map(__FUNCTION__, $r); // recursive function call
}
return $r;
}
答案 29 :(得分:0)
我认为使用trait存储对象到数组转换逻辑是一个好主意。简单的例子
trait ArrayAwareTrait
{
/**
* Return list of Entity's parameters
* @return array
*/
public function toArray()
{
$props = array_flip($this->getPropertiesList());
return array_map(
function ($item) {
if ($item instanceof \DateTime) {
return $item->format(DATE_ATOM);
}
return $item;
},
array_filter(get_object_vars($this), function ($key) use ($props) {
return array_key_exists($key, $props);
}, ARRAY_FILTER_USE_KEY)
);
}
/**
* @return array
*/
protected function getPropertiesList()
{
if (method_exists($this, '__sleep')) {
return $this->__sleep();
}
if (defined('static::PROPERTIES')) {
return static::PROPERTIES;
}
return [];
}
}
class OrderResponse
{
use ArrayAwareTrait;
const PROP_ORDER_ID = 'orderId';
const PROP_TITLE = 'title';
const PROP_QUANTITY = 'quantity';
const PROP_BUYER_USERNAME = 'buyerUsername';
const PROP_COST_VALUE = 'costValue';
const PROP_ADDRESS = 'address';
private $orderId;
private $title;
private $quantity;
private $buyerUsername;
private $costValue;
private $address;
/**
* @param $orderId
* @param $title
* @param $quantity
* @param $buyerUsername
* @param $costValue
* @param $address
*/
public function __construct(
$orderId,
$title,
$quantity,
$buyerUsername,
$costValue,
$address
) {
$this->orderId = $orderId;
$this->title = $title;
$this->quantity = $quantity;
$this->buyerUsername = $buyerUsername;
$this->costValue = $costValue;
$this->address = $address;
}
/**
* @inheritDoc
*/
public function __sleep()
{
return [
static::PROP_ORDER_ID,
static::PROP_TITLE,
static::PROP_QUANTITY,
static::PROP_BUYER_USERNAME,
static::PROP_COST_VALUE,
static::PROP_ADDRESS,
];
}
/**
* @return mixed
*/
public function getOrderId()
{
return $this->orderId;
}
/**
* @return mixed
*/
public function getTitle()
{
return $this->title;
}
/**
* @return mixed
*/
public function getQuantity()
{
return $this->quantity;
}
/**
* @return mixed
*/
public function getBuyerUsername()
{
return $this->buyerUsername;
}
/**
* @return mixed
*/
public function getCostValue()
{
return $this->costValue;
}
/**
* @return string
*/
public function getAddress()
{
return $this->address;
}
}
$orderResponse = new OrderResponse(...);
var_dump($orderResponse->toArray());
答案 30 :(得分:0)
这里我创建了一个 objectToArray()方法,该方法也适用于递归对象,例如当$objectA
包含$objectB
再次指向$objectA
时
此外,我已使用ReflectionClass将输出限制为公共属性。如果你不需要它,摆脱它。
/**
* Converts given object to array, recursively.
* Just outputs public properties.
*
* @param object|array $object
* @return array|string
*/
protected function objectToArray($object) {
if (in_array($object, $this->usedObjects, TRUE)) {
return '**recursive**';
}
if (is_array($object) || is_object($object)) {
if (is_object($object)) {
$this->usedObjects[] = $object;
}
$result = array();
$reflectorClass = new \ReflectionClass(get_class($this));
foreach ($object as $key => $value) {
if ($reflectorClass->hasProperty($key) && $reflectorClass->getProperty($key)->isPublic()) {
$result[$key] = $this->objectToArray($value);
}
}
return $result;
}
return $object;
}
为了识别已经使用过的对象,我在这个(抽象)类中使用了一个名为$this->usedObjects
的受保护属性。如果找到递归嵌套对象,它将被字符串**recursive**
替换。否则它会因为无限循环而失败。
答案 31 :(得分:0)
$Menu = new Admin_Model_DbTable_Menu();
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu();
$Addmenu->populate($row->toArray());