2009-12-08 13 views
12

que estaba hurgando PHPS fundición mecanismo, y corrió en un caso raro cuando fundición una matriz como un objetocasting una matriz con teclas numéricas como un objeto

$o = (object) array('1'=>'/foo/bar'); 
$o = new stdClass(); 
var_dump($o); 

Como lo entiendo, propiedades PHP necesitan estar declarado con las mismas reglas que las variables de PHP. Eso es A valid variable name starts with a letter or underscore, followed by any number of letters, numbers, or underscores. Sin embargo, el código anterior produce la siguiente salida

object(stdClass)#1 (1) { 
    [1]=> 
    string(8) "/foo/bar" 
} 

Lo que se pone realmente extraño es cuando intenta acceder a esa información en el objeto.

var_dump($o->1);  // parse error 
var_dump($o->{'1'});  // NULL 
var_dump(get_object_vars($o)); //array(0) { } 

¿Hay alguna forma para llegar a la información que el var_dump informes está en el objeto, o es sólo encerrado por el resto del ciclo de petición vida? (el uso práctico de esto es nulo, solo tengo curiosidad)

+0

Desde mi experiencia, parece que están encerrados aunque nunca he sido lo suficientemente firme para probar todo. – jlb

+0

este es de hecho el caso, es un problema conocido en PHP. – GSto

+0

Es conocido como conocido por nosotros, o conocido de alguna manera por el equipo de PHP. –

Respuesta

13

Sí, solo están bloqueados a menos que se vuelvan a enviar a una matriz. Hay algunos pequeños "errores" en PHP, por ejemplo, en versiones anteriores, se podía definir una constante como una matriz, pero nunca acceder a sus elementos. Incluso ahora puede definir una constante como recurso (por ejemplo, define('MYSQL',mysql_connect());), aunque esto conduce a un comportamiento bastante impredecible y, nuevamente, debe evitarse.

En general, es mejor evitar los moldes de matriz a objeto si es posible. Si realmente necesita hacer esto, considere la creación de una nueva instancia de stdClass y luego manualmente cambiar el nombre de todas las variables, por ejemplo, para _0, _1, etc.

$a = array('cat','dog','pheasant'); 
$o = new stdClass; 
foreach ($a as $k => $v) { 
    if (is_numeric($k)) { 
     $k = "_{$k}"; 
    } 
    $o->$k = $v; 
} 

EDIT: Sólo hizo una prueba más rápida en esta hipótesis y sí, oficialmente "no existen" en el contexto del objeto; los datos están almacenados, pero es imposible acceder y, por lo tanto, es el último miembro privado. Aquí está la prueba:

$a = array('one','two','three'); 
$o = (object)$a; 
var_dump(property_exists($o, 1), property_exists($o, '1')); 

Y la salida es:

bool(false) 
bool(false) 

nuevo EDIT: Interesante nota lateral, la siguiente operación vuelve falsa:

$a = array('one','two','three','banana' => 'lime'); 
$b = array('one','two','banana' => 'lime'); 

$y = (object)$a; 
$z = (object)$b; 

var_dump($y == $z); 
+2

Esto _es_ en realidad [un error] (https://bugs.php.net/bug.php?id=45959). Se ha considerado "demasiado caro de arreglar" y la resolución ha sido "actualizada la documentación para describir este capricho inútil, por lo que ahora es el comportamiento oficialmente correcto". – lanzz

0

Creo que se obtiene un error porque al convertir una clave entera de una matriz en un objeto/subobjeto se romperán las convenciones de nomenclatura de las varibles de PHP.

Consejos:

  • decidir antes de las manos si usted quiere tener un OBJECT o un ARRAY
  • que tener cuidado con la conversión de tipos (por ejemplo, (objeto) array (1 => 'cadena') no lo haga tales cosas)
  • Use castings para la validación y no convertir las cosas
  • Evitar el uso de objetos como matrices "falsos"
7

Parece que la clase ArrayObject puede acceder a las propiedades

$a = new ArrayObject($obj); 
echo $a[0]; 
+0

Esto es muy útil. ¡Gracias! – SuitedSloth

1

Sí, sólo están encerrados menos fundido de nuevo a una matriz.

Tal vez, las propiedades todavía están allí y son accesibles, simplemente no directamente. Sin embargo, no estoy seguro de cómo foreach funciona internamente (podría lanzar el objeto a una matriz) ya que no he buceado en el código fuente.

Ejemplo:

$array = array('one', 'two', 'three', 'four'); 
$obj = (object) $array; 

foreach ($obj as $key => &$val) { 
    print "$key -> $val<br>"; 
    $val = 'Nhaca'; 
    var_dump($obj); 
} 
print_r($obj); 
print_r($array); 

de salida:

0 -> one 
object(stdClass)[1] 
    &string 'Nhaca' (length=5) 
    string 'two' (length=3) 
    string 'three' (length=5) 
    string 'four' (length=4) 
1 -> two 
object(stdClass)[1] 
    string 'Nhaca' (length=5) 
    &string 'Nhaca' (length=5) 
    string 'three' (length=5) 
    string 'four' (length=4) 
2 -> three 
object(stdClass)[1] 
    string 'Nhaca' (length=5) 
    string 'Nhaca' (length=5) 
    &string 'Nhaca' (length=5) 
    string 'four' (length=4) 
3 -> four 
object(stdClass)[1] 
    string 'Nhaca' (length=5) 
    string 'Nhaca' (length=5) 
    string 'Nhaca' (length=5) 
    &string 'Nhaca' (length=5) 
stdClass Object ([0] => Nhaca [1] => Nhaca [2] => Nhaca [3] => Nhaca) 
Array ([0] => one [1] => two [2] => three [3] => four) 
Cuestiones relacionadas