¿Cómo escribo dinámicamente un nombre de propiedad de objeto PHP?

81

Tengo propiedades de objeto en mi código que se ven así:

$obj ->field_name_cars[0];
$obj ->field_name_clothes[0];

El problema es que tengo cientos de nombres de campo y necesito escribir el nombre de la propiedad de forma dinámica. De lo contrario, el nombre del objeto y las claves de la propiedad siempre serán los mismos. Así que intenté:

$obj -> $field[0];

Esperando que el nombre de la propiedad se cambie dinámicamente y acceda a los valores correctos. Pero, sigo obteniendo 'propiedad indefinida $ campo en stdClass :: $ campo;

Más o menos, estoy intentando escribir dinámicamente el php antes de que se ejecute para que pueda generar los valores adecuados. ¿Pensamientos sobre cómo abordar esto?

usuario658182
fuente

Respuestas:

205

Actualización para PHP 7.0

PHP 7 introdujo cambios en cómo se manejan las variables indirectas y las propiedades en el nivel del analizador (consulte el RFC correspondiente para obtener más detalles). Esto acerca el comportamiento real a lo esperado y significa que en este caso $obj->$field[0]producirá el resultado esperado.

En los casos en que el comportamiento predeterminado (ahora mejorado) no sea deseado, se pueden usar llaves para anularlo como se muestra a continuación.

Respuesta original

Escribe el acceso así:

$obj->{$field}[0]

Este truco de "encerrar con llaves" es útil en PHP siempre que haya ambigüedad debido a variables variables.

Considere el código inicial $obj->$field[0]- ¿esto significa "acceder a la propiedad cuyo nombre se da en $field[0]", o "acceder al elemento con la clave 0de la propiedad cuyo nombre se da en $field"? Las llaves te permiten ser explícito.

Jon
fuente
Esta declaración en bruto funciona en mi código: echo $ json_dump-> geometry [6] -> obs [2] -> hayabusa2-> delay_from; Pero no puedo "simularlo" asignando "geometría [6] -> obs [2] -> hayabusa2-> delay_from" a $ path y usando echo $ json_dump -> {$ path}, obtengo "Propiedad no definida: stdClass: : $ geometry [6] "
jumpjack
31

Creo que está buscando una notación de tipo variable-variable que, al acceder a valores de otras matrices / objetos, se logra mejor utilizando una sintaxis de corchetes como esta:

$obj->{field[0]}
Mike Brant
fuente
12

El método mágico __get is your friend:

class MyClass
{
   private $field = array();

   public function __get($name)
   {
      if(isset($this->field[$name]))
        return $this->field[$name];
      else
        throw new Exception("$name dow not exists");
   }
}

Uso:

$myobj = new MyClass();
echo $myobj->myprop;

Explicación: Todos los datos de su campo se almacenan en una matriz. Al acceder, $myobj->mypropesa propiedad obviamente no existe en la clase. Ahí es donde __getse llama. __getbusca el nombre en la fieldmatriz y devuelve el valor correcto.

JvdBerg
fuente
3
No hagas esto. Las funciones __get son acaparadores de rendimiento que debe evitar usar cuando sea posible, además de crear algunos problemas graves con comportamientos inesperados. Este ejemplo es especialmente aterrador, ya que genera una excepción que puede causar un comportamiento grave de ruptura de la aplicación si el desarrollador no planea acceder a un atributo inexistente para lanzar una excepción, convirtiendo el acceso de un atributo simple en un error fatal potencial.
moberemk
0

aboulfazl, ya que los métodos PHP 5.3.3 con el mismo nombre que la clase no serán tratados como constructores.

    YourClass
    {
        public $any = false;

        public function __construct($any = null)
        {
            $this->any = (is_null($any) ? $this->any : $any);
        }
    }

Esto funciona, pero el propietario del tema no lo preguntó, ¡Jon da la bienvenida!

Everterstraat
fuente
0

Trabajé en un código que usaba propiedades de objeto creadas dinámicamente. Pensé que usar propiedades de objetos creadas dinámicamente era bastante bueno (cierto, en mi opinión). Sin embargo, mi programa tardó 7 segundos en ejecutarse. Eliminé las propiedades del objeto dinámico y las reemplacé por las propiedades del objeto declaradas como parte de cada clase (pública en este caso). El tiempo de CPU pasó de más de 7 segundos a 0,177 segundos. Eso es bastante sustancial.

Es posible que estuviera haciendo algo mal en la forma en que estaba usando las propiedades dinámicas de los objetos. También es posible que mi configuración esté rota de alguna manera. Por supuesto, debería decir que tengo una configuración PHP básica muy simple en mi máquina.

Peter Schaeffer
fuente
0

hoy me enfrento a ese desafío. Terminé con ese estilo de desarrollo

$countTickets = new \stdClass;

foreach ($tickets as $key => $value) {

    if(!isset($countTickets->total)){
        $countTickets->total = 0;
    }

    if(!isset($countTickets->{$value['categoryname']})){
        $countTickets->{$value['categoryname']} = 0;
    }

    $countTickets->total += $value['number'];
    $countTickets->{$value['categoryname']} += $value['number']; 
}
Jordania Georgiadis
fuente
-4

La mejor manera de usar la instancia de objeto de clase predeterminada de PHP para asignarle propiedades dinámicamente

$inst=new \StdClass;
$inst->any_property = '';
Jefe Andrew
fuente
-6

Con herencia. por ejemplo:

YourClass extends stdClass {
   public function YourClass() {
      $this->AnyProperty="any";
   }
}

Ahora AnyProperty se declara dinámicamente.

aboulfazl
fuente