Cómo agregar una propiedad a un objeto en PHP >= 5.3 modo estricto sin generar error

7 minutos de lectura

avatar de usuario
Rayo

Esto tiene que ser simple, pero parece que no puedo encontrar una respuesta …

Tengo un objeto stdClass genérico $foo sin propiedades. Quiero agregar una nueva propiedad $bar a eso que aún no está definido. Si hago esto:

$foo = new StdClass();
$foo->bar="1234";

PHP en modo estricto se queja.

¿Cuál es la forma correcta (fuera de la declaración de clase) de agregar una propiedad a un objeto ya instanciado?

NOTA: Quiero que la solución funcione con el objeto PHP genérico de tipo stdClass.

Un poco de historia sobre este tema. Estoy decodificando una cadena json que es una matriz de objetos json. json_decode() genera una matriz de objetos StdClass. Necesito manipular estos objetos y agregar una propiedad a cada uno.

  • Intenta pasar TRUE como segundo parámetro para json_decode. Le dará una matriz asociativa en lugar de una matriz de objetos.

    – genérico

    23 de julio de 2012 a las 18:54

  • PHP en modo estricto no se queja de eso. 3v4l.org/kn0hi

    – hakré

    18 de abril de 2013 a las 17:09

  • No sé por qué esto se ha cerrado ya que esta es una pregunta perfectamente válida. Tengo una pregunta exactamente similar en este momento.

    – Esteban

    30 mayo 2014 a las 18:14

  • ¿Puede alguna de las personas que votaron a favor de esta pregunta y sus respuestas explicar cuál es exactamente el supuesto error aquí? Incluso el RFC aprobado recientemente que hará que las propiedades dinámicas sean un error en PHP 9.0 los permite explícitamente en stdClass, porque ese es el punto. Solo puedo pensar que en realidad hay alguna herramienta de “estilo de código” que las personas están “engañando” ciegamente con las respuestas a continuación.

    – IMSoP

    18 de enero a las 15:27


avatar de usuario
WWW

Si absolutamente tiene que agregar la propiedad al objeto, creo que podría convertirlo en una matriz, agregar su propiedad (como una nueva clave de matriz) y luego volver a convertirlo en un objeto. La única vez que te encuentras stdClass objetos (creo) es cuando lanzas una matriz como un objeto o cuando creas un nuevo stdClass objeto desde cero (y por supuesto cuando json_decode() algo – ¡tonto de mí por olvidar!).

En vez de:

$foo = new StdClass();
$foo->bar="1234";

harías:

$foo = array('bar' => '1234');
$foo = (object)$foo;

O si ya tenía un objeto stdClass existente:

$foo = (array)$foo;
$foo['bar'] = '1234';
$foo = (object)$foo;

También como 1 liner:

$foo = (object) array_merge( (array)$foo, array( 'bar' => '1234' ) );

  • Un lugar en el que te encuentras con StdClass es cuando decodificas json, lo cual es bastante común.

    – rayo

    23 de julio de 2012 a las 18:48

  • @Ray, estoy sacudiendo la cabeza con tristeza porque no pensé en mencionar eso. =)

    – WWW

    23 de julio de 2012 a las 18:50

  • Su solución funciona, pero me duele el corazón de OO 🙂 Esperaba algún tipo de reflejo llamativo kung foo o algo así… Mantendré la pregunta abierta un poco más y esperaré algo de magia PHP poco conocida.

    – rayo

    23 de julio de 2012 a las 19:03

  • @Ray jejeje… Desearía tener algo más elegante para ti. Por cierto, establecer explícitamente error_reporting(E_STRICT); en PHP 5.3.15-1~dotdeb.0 with Suhosin-Patch, no recibo ningún error o aviso cuando intento establecer una propiedad inexistente en un objeto stdClass. ¿Qué versión de PHP estás usando?

    – WWW

    23 de julio de 2012 a las 19:17


  • Ja, casi tres años después y recibo un voto negativo sin explicación por alguna razón. Gracias.

    – WWW

    21 de marzo de 2016 a las 16:26

avatar de usuario
JM R.

Hazlo asi:

$foo = new stdClass();
$foo->{"bar"} = '1234';

ahora intenta:

echo $foo->bar; // should display 1234

  • Funciona como encanto. Esta debería ser la solución aceptada.

    – Tarraquis

    12/03/2018 a las 20:36

  • ¿Cómo agrega una propiedad a un campo en un objeto usando esta sintaxis?

    – Gran dinero

    14 de agosto de 2018 a las 23:39

  • Error ‘Intento de asignar propiedad de no objeto’ en Laravel

    – Rejaul

    30 de junio de 2019 a las 11:16

  • incluso la cadena “barra” puede estar en una variable: $foo->{$cualquier_variable} = ‘1234’;

    – Salar

    9 de noviembre de 2019 a las 14:12


  • Esta debería ser definitivamente la respuesta aceptada, ya que mantiene intacta la referencia del objeto (que en mi caso fue crucial).

    – Johan Fredrik Varen

    6 de mayo de 2020 a las 11:08

Si desea editar el JSON decodificado, intente obtenerlo como una matriz asociativa en lugar de una matriz de objetos.

$data = json_decode($json, TRUE);

avatar de usuario
Ragnar

Esta es otra manera:

$foo = (object)null; //create an empty object
$foo->bar = "12345";

echo $foo->bar; //12345

avatar de usuario
Benjamín Dubois

deberías usar los métodos mágicos __Set y __get. Ejemplo sencillo:

class Foo
{
    //This array stores your properties
private $content = array();

public function __set($key, $value)
{
            //Perform data validation here before inserting data
    $this->content[$key] = $value;
    return $this;
}

public function __get($value)
{       //You might want to check that the data exists here
    return $this->$content[$value];
}

}

Por supuesto, no use este ejemplo como este: no hay seguridad en absoluto 🙂

EDITAR: visto sus comentarios, aquí podría haber una alternativa basada en la reflexión y un decorador:

 class Foo
 {
private $content = array();
private $stdInstance;

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

public function __set($key, $value)
{
    //Reflection for the stdClass object
    $ref = new ReflectionClass($this->stdInstance);
    //Fetch the props of the object

    $props = $ref->getProperties();

    if (in_array($key, $props)) {
        $this->stdInstance->$key = $value;
    } else {
        $this->content[$key] = $value;
    }
    return $this;
}

public function __get($value)
{
    //Search first your array as it is faster than using reflection
    if (array_key_exists($value, $this->content))
    {
        return $this->content[$value];
    } else {
        $ref = new ReflectionClass($this->stdInstance);

        //Fetch the props of the object
        $props = $ref->getProperties();

        if (in_array($value, $props)) {

        return $this->stdInstance->$value;
    } else {
        throw new \Exception('No prop in here...');
    }
}
 }
}

PD: no probé mi código, solo la idea general …

  • Benjamin, quiero usar la clase de objeto genérico de PHP: StdClass. No puedo modificar esta clase.

    – rayo

    23 de julio de 2012 a las 18:46


  • Ray, actualicé mi respuesta con una solución correspondiente a tu necesidad, pero es pesada :-/

    – Benjamín Dubois

    23 de julio de 2012 a las 18:59

avatar de usuario
ganga

No sé si es la versión más nueva de php, pero esto funciona. estoy usando php 5.6

    <?php
    class Person
    {
       public $name;

       public function save()
       {
          print_r($this);
       }
    }

   $p = new Person;
   $p->name = "Ganga";
   $p->age = 23;

   $p->save();

Este es el resultado. El método save en realidad obtiene la nueva propiedad

    Person Object
    (
       [name] => Ganga
       [age] => 23
    )

  • Benjamin, quiero usar la clase de objeto genérico de PHP: StdClass. No puedo modificar esta clase.

    – rayo

    23 de julio de 2012 a las 18:46


  • Ray, actualicé mi respuesta con una solución correspondiente a tu necesidad, pero es pesada :-/

    – Benjamín Dubois

    23 de julio de 2012 a las 18:59

Sí, es posible agregar dinámicamente propiedades a un objeto PHP.

Esto es útil cuando se recibe un objeto parcial de javascript.

Lado JAVASCRIPT:

var myObject = { name = "myName" };
$.ajax({ type: "POST", url: "index.php",
    data: myObject, dataType: "json",
    contentType: "application/json;charset=utf-8"
}).success(function(datareceived){
    if(datareceived.id >= 0 ) { /* the id property has dynamically added on server side via PHP */ }
});

Lado de PHP:

$requestString = file_get_contents('php://input');
$myObject = json_decode($requestString); // same object as was sent in the ajax call
$myObject->id = 30; // This will dynamicaly add the id property to the myObject object

O SIMPLEMENTE ENVÍE UNA PROPIEDAD DUMMY desde javascript que completará en PHP.

  • Creo que enviar una propiedad ficticia desde JS y completarla en el lado de PHP es la solución más fácil e inteligente. ¡Gracias!

    – Adrián P.

    27/03/2015 a las 21:34


  • o_O O_o o_O O_o

    – las flores del tiempo

    29 de abril de 2015 a las 22:19

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad