¿Cómo convertir una matriz a objeto en PHP?


367

¿Cómo puedo convertir una matriz como esta en objeto?

[128] => Array
    (
        [status] => Figure A.
 Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
    )

[129] => Array
    (
        [status] => The other day at work, I had some spare time
    )

44
¿Qué tipo de objeto quieres conseguir, precisamente? Lo que quiero decir es: ¿cuáles deberían ser los atributos?
Pascal MARTIN

en un bucle que debería tanto porque el estado es una matriz de datos de modo que ambos están printet
streetparade

no estoy seguro de cuándo, pero esto simplemente funciona:$a = (object)['hello' => 'world'];
Nishchal Gautam

Respuestas:


588

En el caso más simple, probablemente sea suficiente "convertir" la matriz como un objeto:

$object = (object) $array;

Otra opción sería crear una instancia de una clase estándar como variable y recorrer su matriz mientras reasigna los valores:

$object = new stdClass();
foreach ($array as $key => $value)
{
    $object->$key = $value;
}

Como señaló Edson Medina , una solución realmente limpia es usar las json_funciones integradas:

$object = json_decode(json_encode($array), FALSE);

Esto también (recursivamente) convierte todas sus sub matrices en objetos, que puede querer o no. Desafortunadamente, tiene un rendimiento de 2-3x sobre el enfoque de bucle.

¡Advertencia! (gracias a Ultra por el comentario):

json_decode en diferentes entornos convierte los datos UTF-8 de diferentes maneras. Termino obteniendo valores '240.00' localmente y '240' en producción: un desastre masivo. Además, si la conversión falla, la cadena se devuelve como NULL


41
"como las variables no pueden comenzar con números", sí pueden: $ object -> {3} = 'xyz';
chelmertz

11
"tiene un éxito de rendimiento de 2-3x", que es una comparación injusta, ya que el último método devuelve objetos recursivos, mientras que el enfoque de bucle sin más condiciones (como en la respuesta de @streetparade) solo convierte el primer nivel.
feeela

8
@feeela No creo que sea injusto en absoluto ... Mencioné que hace la conversión de forma recursiva. Además, el éxito en el rendimiento de 2-3x se logró usando una matriz de entrada plana (que no usaría ninguna recursividad)
jlb

66
¡ADVERTENCIA! json_decode en diferentes entornos convierte los datos UTF-8 de diferentes maneras. Termino obteniendo valores '240.00' localmente y '240' en producción: un desastre masivo. Morover si la conversión falla, la cadena se devuelve como NULL
Szymon Toda

1
Tenga en cuenta que cuando utilice las funciones json_ *: las referencias (por ejemplo, a otras matrices) almacenadas en la matriz original se duplicarán en este caso. Digamos que la clave xen la matriz contiene una referencia a otra matriz. Luego, $object->xdespués de la ejecución de su one-liner, habrá un duplicado de $array['x'], ya no será una referencia a la matriz original. Esto puede ser inofensivo en algunas aplicaciones, pero para matrices grandes desperdicia memoria y puede estropear la ejecución si la referencia se usa más adelante.
El Coprolal

153

simplemente puede usar la conversión de tipos para convertir una matriz en objeto.

// *convert array to object* Array([id]=> 321313[username]=>shahbaz)
$object = (object) $array_name;

//now it is converted to object and you can access it.
echo $object->username;

107

La manera fácil sería

$object = (object)$array;

Pero eso no es lo que quieres. Si quieres objetos, quieres lograr algo, pero eso falta en esta pregunta. Usar objetos solo por el motivo de usar objetos no tiene sentido.


2
no funciona, lo hice antes de hacer la pregunta aquí, así que debe haber otra forma de hacerlo
streetparade

20
¿Por qué tiene que dar su razón para querer usar objetos? No creo que sea relevante para cómo se hace. ¿Quizás necesita json_encodificarlos o serializarlos? Podría haber docenas de razones para hacer esto.
zombat

hmm .. miré la salida del navegador, se ve como este objeto (stdClass) # 150 (130) {[0] => array (1) {["status"] => string (130) "Por fin Mac y Los usuarios de Linux no tienen que sentirse ciudadanos de segunda clase en Chrome Land: tienen una versión beta oficial ... "} oficialmente es un objeto, pero cómo iterar lanzan esto para poder acceder a un estado como $ obj-> status cualquier idea ?
streetparade

zombat, la codificación JSON no es motivo para usar un objeto, hay una bandera para json_encode () para usar objetos. con serializar uno necesitaría un tipo de objeto específico esperado por el receptor. Y en general trato de ayudar con el problema real . Para mí, esta pregunta implica que hay un error arquitectónico en otro lugar.
johannes

bonito, trabajar con laravel array para objetar problema
Anthony Kal

105

Hack rápido:

// assuming $var is a multidimensional array
$obj = json_decode (json_encode ($var), FALSE);

No es bonito, pero funciona.


2
De hecho, me encanta esta solución, usar funciones integradas en lugar de definidas por el usuario siempre es más rápido, y esta funciona muy bien. Gracias por el consejo.
aknatn

@Oddant Esto resuelve el problema mencionado anteriormente (convertir una matriz en un objeto). Tu despotricar debería dirigirse a la publicación principal, no a mi solución.
Edson Medina

@EdsonMedina Lo hice, aunque mi publicación es demasiado baja.
vdegenne

1
@Oddant, para ser justos con @EdsonMedina, la pregunta original no especifica qué visibilidad necesitan los atributos, y dado que OP no se usa $thisen los comentarios que siguen como accesor, está muy implícito que desea una stdClassinstancia como salida y no una clase definida por el usuario como la que usa su respuesta. Estoy de acuerdo con la elegancia de esta solución, pero desafortunadamente es un patrón muy comúnmente empleado para resolver este problema con matrices anidadas donde la conversión a objetos no funcionará. También es posible que OP esté usando una interfaz que requiera un objeto como entrada y no una matriz.
DeaconDesperado

3
No olvides que de esta manera perderás todo menos los tipos básicos. DateTime será convertidor stdObject por ejemplo.
Denis Pshenov el

97

Aquí hay tres formas:

  1. Fingir un objeto real:

    class convert
    {
        public $varible;
    
        public function __construct($array)
        {
            $this = $array;
        }
    
        public static function toObject($array)
        {
            $array = new convert($array);
            return $array;
        }
    }
  2. Convierta la matriz en un objeto convirtiéndolo en un objeto:

    $array = array(
        // ...
    );
    $object = (object) $array;
  3. Convierta manualmente la matriz en un objeto:

    $object = object;
    foreach ($arr as $key => $value) {
        $object->{$key} = $value;
    }

2
hmm gracias pero tu clase de rostro da el siguiente error Error grave: no se puede reasignar $ this en /var/www/bot/inc/twitter-bot.php en la línea 10
streetparade

1
y typcasint @ reference no es una buena idea, incluso si no funcionara aquí es lo que obtuve inesperado T_OBJECT_CAST, esperando T_NEW o T_STRING o T_VARIABLE o '$'
streetparade

2
$ array = & (objeto) $ array == ¡buena implementación de KISS!
mate64

16
¿Por qué alguien querría usar un método diferente al 2)? ¿Hay alguna desventaja?
Yogu

77
convertir una matriz en un objeto no funciona en matrices anidadas
minhajul

34

Su forma simple, esto creará un objeto para matrices recursivas también:

$object = json_decode(json_encode((object) $yourArray), FALSE);

44
pasar falsea json_decode()devolverá una matriz asociativa.
Rust

3
@ user3284463 Pasar truea json_decodedevolverá una matriz asociativa, falsees el valor predeterminado y devolverá una StdClassinstancia.
Elliot Reed

24

Dependiendo de dónde lo necesite y de cómo acceder al objeto, hay diferentes formas de hacerlo.

Por ejemplo: simplemente escríbalo

$object =  (object) $yourArray;

Sin embargo, el más compatible es usar un método de utilidad (que aún no forma parte de PHP) que implementa la conversión estándar de PHP basada en una cadena que especifica el tipo (o al ignorarlo simplemente desreferenciando el valor):

/**
 * dereference a value and optionally setting its type
 *
 * @param mixed $mixed
 * @param null  $type (optional)
 *
 * @return mixed $mixed set as $type
 */
function rettype($mixed, $type = NULL) {
    $type === NULL || settype($mixed, $type);
    return $mixed;
}

El ejemplo de uso en su caso ( demostración en línea ):

$yourArray = Array('status' => 'Figure A. ...');

echo rettype($yourArray, 'object')->status; // prints "Figure A. ..."

17

Este me funcionó

  function array_to_obj($array, &$obj)
  {
    foreach ($array as $key => $value)
    {
      if (is_array($value))
      {
      $obj->$key = new stdClass();
      array_to_obj($value, $obj->$key);
      }
      else
      {
        $obj->$key = $value;
      }
    }
  return $obj;
  }

function arrayToObject($array)
{
 $object= new stdClass();
 return array_to_obj($array,$object);
}

uso:

$myobject = arrayToObject($array);
print_r($myobject);

devoluciones :

    [127] => stdClass Object
        (
            [status] => Have you ever created a really great looking website design
        )

    [128] => stdClass Object
        (
            [status] => Figure A.
 Facebook's horizontal scrollbars showing up on a 1024x768 screen resolution.
        )

    [129] => stdClass Object
        (
            [status] => The other day at work, I had some spare time
        )

como de costumbre, puedes repetirlo como:

foreach($myobject as $obj)
{
  echo $obj->status;
}

Pero este es aproximadamente un 500% más lento (probado) que el tipo de conversión: $ obj = (objeto) $ array;
xZero

@xZero pero $obj = (object) $array;no funciona para matrices multidimensionales.
Jeff Puckett

15

No hay ningún método incorporado para hacerlo, que yo sepa, pero es tan fácil como un simple ciclo:

    $obj= new stdClass();

    foreach ($array as $k=> $v) {
        $obj->{$k} = $v;
    }

Puede exponer eso si lo necesita para construir su objeto de forma recursiva.


15

Puede usar la función (objeto) para convertir su matriz en un objeto.

$arr= [128=> ['status'=>
                 'Figure A. Facebook \'s horizontal scrollbars showing up on a 1024x768 screen resolution.'],
                  129=>['status'=>'The other day at work, I had some spare time']];

            $ArrToObject=(object)$arr;
            var_dump($ArrToObject);

El resultado será un objeto que contiene matrices:

object (stdClass) # 1048 (2) {[128] => array (1) {

["status"] => string (87) "Figura A. Las barras de desplazamiento horizontales de Facebook aparecen en una resolución de pantalla de 1024x768". }

[129] => array (1) {["status"] => string (44) "El otro día en el trabajo, tuve algo de tiempo libre"}}


9

En realidad, si desea usar esto con matrices multidimensionales, querrá usar algo de recursión.

static public function array_to_object(array $array)
{
    foreach($array as $key => $value)
    {
        if(is_array($value))
        {
            $array[$key] = self::array_to_object($value);
        }
    }
    return (object)$array;
}

8

Definitivamente iría con una forma limpia como esta:

<?php

class Person {

  private $name;
  private $age;
  private $sexe;

  function __construct ($payload)
  {
     if (is_array($payload))
          $this->from_array($payload);
  }


  public function from_array($array)
  {
     foreach(get_object_vars($this) as $attrName => $attrValue)
        $this->{$attrName} = $array[$attrName];
  }

  public function say_hi ()
  {
     print "hi my name is {$this->name}";
  }
}

print_r($_POST);
$mike = new Person($_POST);
$mike->say_hi();

?>

si envía:

formulaire

obtendrás esto:

Miguel

Encontré esto más lógico al comparar las respuestas anteriores de Objetos que deberían usarse para el propósito para el que fueron hechas (pequeños objetos lindos encapsulados).

El uso de get_object_vars también garantiza que no se creen atributos adicionales en el Objeto manipulado (no desea que un automóvil tenga un apellido, ni una persona que se comporte 4 ruedas).


¿Por qué no utiliza $ attr_value en lugar de $ array [$ attr_name]; en su función pública from_array ($ array) función
Sakkeer Hussain

7

También podría usar un ArrayObject, por ejemplo:

<?php
    $arr = array("test",
                 array("one"=>1,"two"=>2,"three"=>3), 
                 array("one"=>1,"two"=>2,"three"=>3)
           );
    $o = new ArrayObject($arr);
    echo $o->offsetGet(2)["two"],"\n";
    foreach ($o as $key=>$val){
        if (is_array($val)) {
            foreach($val as $k => $v) {
               echo $k . ' => ' . $v,"\n";
            }
        }
        else
        {
               echo $val,"\n";
        }
    }
?>

//Output:
  2
  test
  one => 1
  two => 2
  three => 3
  one => 1
  two => 2
  three => 3

1
En mi opinión, esta debería ser la mejor respuesta. Más información herre: php.net/manual/en/arrayobject.construct.php
Julian

7

El que uso (es un miembro de la clase):

const MAX_LEVEL = 5; // change it as needed

public function arrayToObject($a, $level=0)
{

    if(!is_array($a)) {
        throw new InvalidArgumentException(sprintf('Type %s cannot be cast, array expected', gettype($a)));
    }

    if($level > self::MAX_LEVEL) {
        throw new OverflowException(sprintf('%s stack overflow: %d exceeds max recursion level', __METHOD__, $level));
    }

    $o = new stdClass();
    foreach($a as $key => $value) {
        if(is_array($value)) { // convert value recursively
            $value = $this->arrayToObject($value, $level+1);
        }
        $o->{$key} = $value;
    }
    return $o;
}

7

Técnica poco complicada pero fácil de extender:

Supongamos que tienes una matriz

$a = [
     'name' => 'ankit',
     'age' => '33',
     'dob' => '1984-04-12'
];

Suponga que tiene una clase Person que puede tener más o menos atributos de esta matriz. por ejemplo

class Person 
{
    private $name;
    private $dob;
    private $age;
    private $company;
    private $city;
}

Si todavía quieres cambiar tu matriz al objeto persona. Puede usar la clase ArrayIterator.

$arrayIterator = new \ArrayIterator($a); // Pass your array in the argument.

Ahora tienes un objeto iterador.

Cree una clase que extienda la clase FilterIterator; donde tienes que definir el método abstracto aceptar. Sigue el ejemplo

class PersonIterator extends \FilterIterator
{
    public function accept()
    {
        return property_exists('Person', parent::current());
    }
}

La implementación anterior vinculará la propiedad solo si existe en la clase.

Agregue un método más en la clase PersonIterator

public function getObject(Person $object)
{
        foreach ($this as $key => $value)
        {
            $object->{'set' . underscoreToCamelCase($key)}($value);
        }
        return $object;
}

Asegúrese de tener mutadores definidos en su clase. Ahora está listo para llamar a estas funciones donde desea crear objetos.

$arrayiterator = new \ArrayIterator($a);
$personIterator = new \PersonIterator($arrayiterator);

$personIterator->getObject(); // this will return your Person Object. 

6

la recursividad es tu amiga:

function __toObject(Array $arr) {
    $obj = new stdClass();
    foreach($arr as $key=>$val) {
        if (is_array($val)) {
            $val = __toObject($val);
        }
        $obj->$key = $val;
    }

    return $obj;
}

6

Esto requiere PHP7 porque elegí usar una función lambda para bloquear el 'innerfunc' dentro de la función principal. La función lambda se llama recursivamente, de ahí la necesidad de: "use (& $ innerfunc)". Puede hacerlo en PHP5 pero no puede ocultar el innerfunc.

function convertArray2Object($defs) {
    $innerfunc = function ($a) use ( &$innerfunc ) {
       return (is_array($a)) ? (object) array_map($innerfunc, $a) : $a; 
    };
    return (object) array_map($innerfunc, $defs);
}

5

use esta función que hice:

function buildObject($class,$data){
    $object = new $class;
    foreach($data as $key=>$value){
        if(property_exists($class,$key)){
            $object->{'set'.ucfirst($key)}($value);
        }
    }
    return $object;
}

Uso:

$myObject = buildObject('MyClassName',$myArray);

5

un trazador de líneas

$object= json_decode(json_encode($result_array, JSON_FORCE_OBJECT));

1
Tenga en cuenta que las referencias (por ejemplo, a otras matrices) almacenadas en la matriz original serán duplicadas por esta línea. Digamos que la clave xen la matriz contiene una referencia a otra matriz. Luego, $object->xdespués de la ejecución de su línea única, habrá un duplicado de $result_array['x'], no la matriz idéntica.
El Coprolal

4

Fácil:

$object = json_decode(json_encode($array));

Ejemplo:

$array = array(
    'key' => array(
        'k' => 'value',
    ),
    'group' => array('a', 'b', 'c')
);

$object = json_decode(json_encode($array));

Entonces, lo siguiente es cierto:

$object->key->k === 'value';
$object->group === array('a', 'b', 'c')

1
Creo que esta es una solución alternativa. ¿Por qué codificar una matriz a json y luego decodificarla? No es una decisión óptima para mí.
Julián

1
@Julian, debido a que funciona de forma recursiva, lo hace de una manera adecuadamente definida y suficientemente confiable ("estándar"), y también es lo suficientemente rápido como para ser una buena alternativa a la magia aleatoria de mono codificada a mano.
Sz.

3

También puede hacer esto agregando (objeto) a la izquierda de la variable para crear un nuevo objeto.

<?php
$a = Array
    ( 'status' => " text" );
var_dump($a);
$b = (object)$a;
var_dump($b);
var_dump($b->status);

http://codepad.org/9YmD1KsU


1
quizás valga la pena mencionar que esto se llama "casting" o "tipo casting": php.net/manual/en/… y el comportamiento de (object) array () se documenta aquí: php.net/manual/en/…
Pete

2

El uso json_encodees problemático debido a la forma en que maneja los datos que no son UTF-8. Vale la pena señalar que el método json_encode/ json_encodetambién deja matrices no asociativas como matrices. Esto puede o no ser lo que quieres. Recientemente estuve en la posición de necesitar recrear la funcionalidad de esta solución pero sin usar json_funciones. Esto es lo que se me ocurrió:

/**
 * Returns true if the array has only integer keys
 */
function isArrayAssociative(array $array) {
    return (bool)count(array_filter(array_keys($array), 'is_string'));
}

/**
 * Converts an array to an object, but leaves non-associative arrays as arrays. 
 * This is the same logic that `json_decode(json_encode($arr), false)` uses.
 */
function arrayToObject(array $array, $maxDepth = 10) {
    if($maxDepth == 0) {
        return $array;
    }

    if(isArrayAssociative($array)) {
        $newObject = new \stdClass;
        foreach ($array as $key => $value) {
            if(is_array($value)) {
                $newObject->{$key} = arrayToObject($value, $maxDepth - 1);
            } else {
                $newObject->{$key} = $value;
            }
        }
        return $newObject;
    } else {

        $newArray = array();
        foreach ($array as $value) {
            if(is_array($value)) {
                $newArray[] = arrayToObject($value, $maxDepth - 1);
            } else {
                $newArray[] = $value;
            }                
        }
        return $newArray;
    }
}

2

El mejor método en el mundo :)

function arrayToObject($conArray)
{
    if(is_array($conArray)){
        /*
        * Return array converted to object
        * Using __FUNCTION__ (Magic constant)
        * for recursive call
        */
        return (object) array_map(__FUNCTION__, $conArray);
    }else{
        // Return object
        return $conArray;
    }
}

Si utiliza diferentes métodos, tendrá problemas. Este es el mejor método. Alguna vez has visto.


2

Matrices multidimensionales en un objeto. Este código se utiliza para la conversión del método de prueba y captura de la API de búsqueda de Bing.

try {
        // Perform the Web request and get the JSON response
        $context = stream_context_create($options);
        $results = file_get_contents($url . "?cc=" . $country . "&category=" . $type, false, $context);
        $results = json_decode($results);
        return response()->json($results);
    } catch (\Exception $e) {
        $results = array('value' => array(
                (object) array(
                    "name" => "Unable to Retrive News",
                    "url" => "http://www.sample.com/",
                    "image" => (object) array("thumbnail" => (object) array("contentUrl" => "")),
                    "publishedAt" => "",
                    "description" => "")
            )
        );
        $results = (object) $results;
        return response()->json($results);
    }

2

Puedes usar Reflection:

<?php

$array = ['name'=>'maria','age'=>33];

class Person {

    public $name;
    public $age;

    public function __construct(string $name, string $age){
        $this->name  = $name;
        $this->age = $age;
    }
}

function arrayToObject(array $array, string $class_name){

    $r = new ReflectionClass($class_name);
    $object = $r->newInstanceWithoutConstructor();
    $list = $r->getProperties();
    foreach($list as $prop){
      $prop->setAccessible(true);
      if(isset($array[$prop->name]))
        $prop->setValue($object, $array[$prop->name]);
    } 

    return $object;

}

$pessoa1 = arrayToObject($array, 'Person');
var_dump($pessoa1);

1

CakePHP tiene una clase recursiva Set :: map que básicamente asigna una matriz a un objeto. Es posible que deba cambiar el aspecto de la matriz para que el objeto se vea como lo desea.

http://api.cakephp.org/view_source/set/#line-158

En el peor de los casos, es posible que pueda obtener algunas ideas de esta función.


1

Obviamente, solo una extrapolación de las respuestas de otras personas, pero aquí está la función recursiva que convertirá cualquier matriz tridimensional en un objeto:

   function convert_array_to_object($array){
      $obj= new stdClass();
      foreach ($array as $k=> $v) {
         if (is_array($v)){
            $v = convert_array_to_object($v);   
         }
         $obj->{strtolower($k)} = $v;
      }
      return $obj;
   }

Y recuerda que si la matriz tenía teclas numéricas que todavía puede hacer referencia en el objeto resultante mediante el uso {}(por ejemplo: $obj->prop->{4}->prop)


1

Inspirado por todos estos códigos, traté de crear una versión mejorada con soporte para: nombre de clase específico, evitar el método del constructor, el patrón 'beans' y el modo estricto (establecer solo las propiedades existentes):

    class Util {

static function arrayToObject($array, $class = 'stdClass', $strict = false) {
        if (!is_array($array)) {
            return $array;
        }

        //create an instance of an class without calling class's constructor
        $object = unserialize(
                sprintf(
                        'O:%d:"%s":0:{}', strlen($class), $class
                )
        );

        if (is_array($array) && count($array) > 0) {
            foreach ($array as $name => $value) {
                $name = strtolower(trim($name));
                if (!empty($name)) {

                    if(method_exists($object, 'set'.$name)){
                        $object->{'set'.$name}(Util::arrayToObject($value));
                    }else{
                        if(($strict)){

                            if(property_exists($class, $name)){

                                $object->$name = Util::arrayToObject($value); 

                            }

                        }else{
                            $object->$name = Util::arrayToObject($value); 
                        }

                    }

                }
            }
            return $object;
        } else {
            return FALSE;
        }
        }
}

1

Código

Esta función funciona igual que json_decode(json_encode($arr), false).

function arrayToObject(array $arr)
{
    $flat = array_keys($arr) === range(0, count($arr) - 1);
    $out = $flat ? [] : new \stdClass();

    foreach ($arr as $key => $value) {
        $temp = is_array($value) ? $this->arrayToObject($value) : $value;

        if ($flat) {
            $out[] = $temp;
        } else {
            $out->{$key} = $temp;
        }
    }

    return $out;
}

Pruebas

Prueba 1: matriz plana

$arr = ["a", "b", "c"];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));

Salida:

array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)
array(
    0 => 'a',
    1 => 'b',
    2 => 'c',
)

Prueba 2: matriz de objetos

$arr = [["a" => 1], ["a" => 1], ["a" => 1]];
var_export(json_decode(json_encode($arr)));
var_export($this->arrayToObject($arr));

Salida:

array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)
array(
    0 => stdClass::__set_state(array('a' => 1,)),
    1 => stdClass::__set_state(array('a' => 1,)),
    2 => stdClass::__set_state(array('a' => 1,)),
)

Prueba 3: objeto

$arr = ["a" => 1];
var_export(json_decode($arr));
var_export($this->arrayToObject($arr));

Salida:

stdClass::__set_state(array('a' => 1,))
stdClass::__set_state(array('a' => 1,))

0

Lo he hecho de manera bastante simple,

    $list_years         = array();
    $object             = new stdClass();

    $object->year_id   = 1 ;
    $object->year_name = 2001 ;
    $list_years[]       = $object;
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.