php properties

¿Cómo puedo acceder a una propiedad de objeto profundo denominada variable(notación de punto) en php?



properties (5)

Hay muchas preguntas similares a esto, sin embargo, esto es ligeramente diferente ya que se trata de acceso a propiedades de objetos profundos, no solo un nivel de profundidad.

Digamos que tengo una variable que contiene la cadena foo.bar .

$user = new User(); $user->foo = new Foo(); $user->foo->bar = "Hello World"; $variable = "foo.bar"

Me gustaría hacer eco de $user->foo->bar haciendo uso de $variable :

echo $user->foo->bar

Esto es lo que he intentado hasta ahora pero sin éxito (dice NULL ):

$value = str_replace(".", "->", $value); echo $user->{$value};


Es muy fácil reducir la ruta del objeto utilizando la notación de propiedad variable ( $o->$p ):

$path = ''foo.bar''; echo array_reduce(explode(''.'', $path), function ($o, $p) { return $o->$p; }, $user);

Esto podría convertirse fácilmente en una pequeña función auxiliar.


Estoy publicando esto como un cumplido a una respuesta ( ¿Cómo escribir getter / setter para acceder a una matriz de varios niveles por nombres clave? ) Que hace lo mismo para las matrices.

Cree la matriz $path mediante explode() (o agregue a la función), luego use referencias.

$path = explode(''.'', $variable);

Adquiridor

function get($path, $object) { $temp = &$object; foreach($path as $var) { $temp =& $temp->$var; } return $temp; } $value = get($path, $user);

Y, por supuesto, el mal eval() , no recomendado:

$value = str_replace(''.'', ''->'', $variable); eval("echo /$user->$value;");



Puede usar este paquete JSON usando Composer:

composer require machitgarha/json

Por ejemplo:

$userJson = new MAChitgarha/Component/JSON(new User()); $userJson->set("foo", new Foo()); $userJson->set("foo.bar", "Hello World"); $userJson->get("foo.bar"); // Hello World


Se agregó una pequeña mejora a la publicación @deceze.

Esto permite manejar casos en los que también necesita pasar por matrices.

$path = ''foo.bar.songs.0.title''; echo array_reduce(explode(''.'', $path), function ($o, $p) { return is_numeric($p) ? $o[$p] : $o->$p; }, $user);

Editar:

Y si tiene PHP 7+, lo siguiente devolverá nulo de forma segura si el nombre de una propiedad está mal escrito o si no existe.

$path = ''foo.bar.songs.0FOOBAR.title''; echo array_reduce(explode(''.'', $path), function ($o, $p) { return is_numeric($p) ? ($o[$p] ?? null) : ($o->$p ?? null); }, $user);