Converteer een PHP-object naar een associatieve array

Ik integreer een API in mijn website die werkt met gegevens die zijn opgeslagen in objecten terwijl mijn code wordt geschreven met behulp van arrays.

Ik wil graag een quick-and-dirty-functie om een ​​object naar een array te converteren.


Antwoord 1, autoriteit 100%

Gewoon getypt

$array = (array) $yourObject;

Van Arrays:

Als een object wordt geconverteerd naar een array, is het resultaat een array waarvan de elementen de eigenschappen van het object zijn. De sleutels zijn de namen van de lidvariabelen, met een paar opmerkelijke uitzonderingen: integer-eigenschappen zijn niet toegankelijk; privévariabelen hebben de klassenaam voor de variabelenaam; beveiligde variabelen hebben een ‘*’ voor de variabelenaam. Deze toegevoegde waarden hebben null-bytes aan beide kanten.

Voorbeeld: eenvoudig object

$object = new StdClass;
$object->foo = 1;
$object->bar = 2;
var_dump( (array) $object );

Uitvoer:

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

Voorbeeld: complex object

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

Uitvoer (met \0s voor de duidelijkheid bewerkt):

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

Uitvoer met var_exportin plaats van var_dump:

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

Als u op deze manier typt, wordt de objectgrafiek niet diep gecast en moet u de null-bytes toepassen (zoals uitgelegd in het handmatige citaat) om toegang te krijgen tot niet-openbare attributen. Dit werkt dus het beste bij het casten van StdClass-objecten of objecten met alleen openbare eigenschappen. Voor snel en vies (waar je om vroeg) is het prima.

Zie ook deze uitgebreide blogpost:


Antwoord 2, autoriteit 27%

U kunt diep geneste objecten snel converteren naar associatieve arrays door te vertrouwen op het gedrag van de JSON-codeer-/decodeerfuncties:

$array = json_decode(json_encode($nested_object), true);

Antwoord 3, autoriteit 5%

Van de eerste Google-hit voor “PHP-object naar assoc-array” hebben we dit:

function object_to_array($data)
{
    if (is_array($data) || is_object($data))
    {
        $result = [];
        foreach ($data as $key => $value)
        {
            $result[$key] = (is_array($data) || is_object($data)) ? object_to_array($value) : $value;
        }
        return $result;
    }
    return $data;
}

De bron is op codesnippets.joyent.com.


Om het te vergelijken met de oplossing van json_decode & json_encode, deze lijkt sneller. Hier is een willekeurige benchmark (met behulp van de eenvoudige tijdmeting):

$obj = (object) [
    'name'    =>'Mike',
    'surname' =>'Jovanson',
    'age'     =>'45',
    'time'    =>1234567890,
    'country' =>'Germany',
];
##### 100 000 cycles ######
* json_decode(json_encode($var))   : 4.15 sec
* object_to_array($var)            : 0.93 sec

Antwoord 4, autoriteit 4%

Als uw objecteigenschappen openbaar zijn, kunt u het volgende doen:

$array =  (array) $object;

Als ze privé of beveiligd zijn, hebben ze rare sleutelnamen in de array. In dit geval heb je dus de volgende functie nodig:

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

Antwoord 5

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());

Uitvoer

array(2) {
    ["b"]=>
    string(3) "two"
    ["Testc"]=>
    int(1)
}
array(1) {
    ["b"]=>
    string(3) "two"
}

Antwoord 6

Hoe zit het met get_object_vars($obj)? Het lijkt handig als u alleen toegang wilt tot de openbare eigenschappen van een object.

Zie get_object_vars.


Antwoord 7

Hier is wat code:

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

Antwoord 8

Alle andere antwoorden die hier worden gepost, werken alleen met openbare attributen. Hier is een oplossing die werkt met JavaBeans-achtige objecten die reflectie en getters gebruiken:

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

Antwoord 9

Type cast je object naar een array.

$arr =  (array) $Obj;

Het lost je probleem op.


Antwoord 10

Om een ​​object naar een array te converteren, cast het gewoon expliciet:

$name_of_array = (array) $name_of_object;

Antwoord 11

Allereerst, als u een array van een object nodig hebt, moet u de gegevens waarschijnlijk eerst als een array samenstellen. Denk er eens over na.

Gebruik geen foreach-instructie of JSON-transformaties. Als je dit van plan bent, werk je opnieuw met een gegevensstructuur, niet met een object.

Als je het echt nodig hebt, gebruik dan een objectgeoriënteerde benadering om een ​​schone en onderhoudbare code te hebben. Bijvoorbeeld:

Object als array

class PersonArray implements \ArrayAccess, \IteratorAggregate
{
    public function __construct(Person $person) {
        $this->person = $person;
    }
    // ...
 }

Als je alle eigenschappen nodig hebt, gebruik dan een overdrachtsobject:

class PersonTransferObject
{
    private $person;
    public function __construct(Person $person) {
        $this->person = $person;
    }
    public function toArray() {
        return [
            // 'name' => $this->person->getName();
        ];
    }
 }

Antwoord 12

U kunt deze functie gemakkelijk gebruiken om het resultaat te krijgen:

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

Gebruik PHP 5of hoger.


Antwoord 13

Hier is mijn recursieve PHP-functie om PHP-objecten naar een associatieve array te converteren:

// ---------------------------------------------------------
// ----- object_to_array_recursive --- 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_recursive($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_recursive($val);
            }
            else {
                $res_arr[$akey] = (empty($val)) ? $empty : (string)$val;
            }
            $i++;
        }
    }
    return $res_arr;
}
// ---------------------------------------------------------
// ---------------------------------------------------------

Gebruiksvoorbeeld:

// ---- Return associative array from object, ... use:
$new_arr1 = object_to_array_recursive($my_object);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, TRUE);
// -- or --
// $new_arr1 = object_to_array_recursive($my_object, 1);
// ---- Return numeric array from object, ... use:
$new_arr2 = object_to_array_recursive($my_object, FALSE);

Antwoord 14

Je kunt ook een functie in PHP maken om een ​​objectarray te converteren:

function object_to_array($object) {
    return (array) $object;
}

Antwoord 15

Gebruik:

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

Het geeft een array terug zonder speciale tekens en klassenamen.


Antwoord 16

Misschien wilt u dit doen wanneer u gegevens als objecten uit databases verkrijgt:

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

Antwoord 17

Aangepaste functie om stdClass naar een array te converteren:

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

Nog een aangepaste functie om Array naar stdClass te converteren:

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

Gebruiksvoorbeeld:

// 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);

Antwoord 18

Dit antwoord is slechts de combinatie van de verschillende antwoorden van dit bericht, maar het is de oplossing om een ​​PHP-object met openbare of privé-eigenschappen met eenvoudige waarden of arrays om te zetten in een associatieve array…

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

Antwoord 19

Enkele verbeteringen aan de “bekende” code

/*** 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

Merk op dat als de functie lid is van een klasse (zoals hierboven) u __FUNCTION__moet wijzigen in __METHOD__


Antwoord 20

Korte oplossing van @SpYk3HH

function objectToArray($o)
{
    $a = array();
    foreach ($o as $k => $v)
        $a[$k] = (is_array($v) || is_object($v)) ? objectToArray($v): $v;
    return $a;
}

Antwoord 21

U kunt ook De Symfony Serializer Component

gebruiken

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

Antwoord 22

Voor jouw geval was het juist/mooi als je de patronen “decorator” of “datummodeltransformatie” zou gebruiken. Bijvoorbeeld:

Uw model

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

Decorateur

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(),
        ];
    }
}

Gebruik

$car = new Car();
$car->setType('type#');
$car->setModel('model#1');
$car->setColor(255);
$carDecorator = new CarArrayDecorator($car);
$carResponseData = $carDecorator->getArray();

Dus het wordt een mooiere en correctere code.


Antwoord 23

Vervelende sterren converteren en verwijderen:

$array = (array) $object;
foreach($array as $key => $val)
{
    $new_array[str_replace('*_', '', $key)] = $val;
}

Waarschijnlijk is het goedkoper dan het gebruik van reflecties.


Antwoord 24

Hier is mijn voorstel, als je objecten hebt in objecten met zelfs privé-leden:

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

Antwoord 25

Aangezien veel mensen deze vraag vinden omdat ze problemen hebben met het dynamisch benaderen van attributen van een object, wil ik je erop wijzen dat je dit in PHP kunt doen: $valueRow->{"valueName"}

In context (HTML-uitvoer verwijderd voor leesbaarheid):

$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 .= " ";
        }
    }
}

Antwoord 26

Door typecasting te gebruiken, kunt u uw probleem oplossen.
Voeg gewoon de volgende regels toe aan uw retourobject:

$arrObj = array(yourReturnedObject);

Je kunt er ook een nieuw sleutel- en waardepaar aan toevoegen met:

$arrObj['key'] = value;

Antwoord 27

Ik denk dat het een leuk idee is om eigenschappen te gebruiken om logica voor het converteren van objecten naar array op te slaan. Een eenvoudig voorbeeld:

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());

Antwoord 28

Ik gebruik dit (recursieve oplossing met de juiste sleutels nodig):

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

Voorbeeld van gebruik, de volgende code:

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)

Zal dit afdrukken:

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

Antwoord 29

$Menu = new Admin_Model_DbTable_Menu(); 
$row = $Menu->fetchRow($Menu->select()->where('id = ?', $id));
$Addmenu = new Admin_Form_Addmenu(); 
$Addmenu->populate($row->toArray());

Antwoord 30

Hier heb ik een objectToArray()methode gemaakt, die ook werkt met recursieve objecten, zoals wanneer $objectA$objectBbevat die wijst opnieuw naar $objectA.

Bovendien heb ik de uitvoer beperkt tot openbare eigenschappen met behulp van ReflectionClass. Doe het weg als je het niet nodig hebt.

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

Om reeds gebruikte objecten te identificeren, gebruik ik een beschermde eigenschap in deze (abstracte) klasse, genaamd $this->usedObjects. Als een recursief genest object wordt gevonden, wordt het vervangen door de tekenreeks **recursive**. Anders zou het mislukken vanwege een oneindige lus.

LEAVE A REPLY

Please enter your comment!
Please enter your name here

6 + 17 =

Other episodes