¿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;");
No hay una manera fácil de hacerlo.
Afortunadamente, muchas personas quieren hacer esto, por lo que hay bibliotecas que lo admiten, como PropertyAccessor de Symfony:
http://symfony.com/doc/current/components/property_access.html
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);