2008-09-15 17 views
21

Me gustaría poder escribir una clase de PHP que se comporte como una matriz y utilice la sintaxis de matriz normal para obtener la configuración &.Hacer que un objeto PHP se comporte como una matriz?

Por ejemplo (donde foo es una clase PHP de mi toma):

$foo = new Foo(); 

$foo['fooKey'] = 'foo value'; 

echo $foo['fooKey']; 

sé que PHP tiene la _GET y _ID métodos mágicos, pero esos no permitirá utilizar la notación de matriz para acceder a los elementos. Python lo maneja al sobrecargar __getitem__ y __setitem__.

¿Hay alguna manera de hacer esto en PHP? Si hace una diferencia, estoy ejecutando PHP 5.2.

Respuesta

35

Si extiende ArrayObject o implementa ArrayAccess entonces puede hacer lo que quiera.

+0

Muy bueno. Parece que ninguno de estos se puede usar con funciones de matriz como array_key_exists, etc. ¿Es correcto? –

+0

Correcto, use el método offsetExist() en su lugar. –

+0

¿Haría eso en el objeto instanciado? if ($ foo-> offsetExists ('fooKey')) {} –

2

No, fundición tiene en cuanto matriz PHP normales - perder cualquier funcionalidad de su clase derivada de ArrayObject tenía. Mira esto:

class CaseInsensitiveArray extends ArrayObject { 
    public function __construct($input = array(), $flags = 0, $iterator_class =  'ArrayIterator') { 
     if (isset($input) && is_array($input)) { 
      $tmpargs = func_get_args(); 
      $tmpargs[0] = array_change_key_case($tmpargs[0], CASE_LOWER); 
      return call_user_func_array(array('parent', __FUNCTION__), $tmp args); 
     } 
     return call_user_func_array(array('parent', __FUNCTION__), func_get_args()); 
    } 

    public function offsetExists($index) { 
     if (is_string($index)) return parent::offsetExists(strtolower($index)); 
     return parent::offsetExists($index); 
    } 

    public function offsetGet($index) { 
     if (is_string($index)) return parent::offsetGet(strtolower($index)); 
     return parent::offsetGet($index); 
    } 

    public function offsetSet($index, $value) { 
     if (is_string($index)) return parent::offsetSet(strtolower($index, $value)); 
     return parent::offsetSet($index, $value); 
    } 

    public function offsetUnset($index) { 
     if (is_string($index)) return parent::offsetUnset(strtolower($index)); 
     return parent::offsetUnset($index); 
    } 
} 

$blah = new CaseInsensitiveArray(array(
    'A'=>'hello', 
    'bcD'=>'goodbye', 
    'efg'=>'Aloha', 
)); 

echo "is array: ".is_array($blah)."\n"; 

print_r($blah); 
print_r(array_keys($blah)); 

echo $blah['a']."\n"; 
echo $blah['BCD']."\n"; 
echo $blah['eFg']."\n"; 
echo $blah['A']."\n"; 

Como era de esperar, los array_keys() falla. Además, is_array ($ blah) devuelve falso. Pero si cambia la línea constructor para:

$blah = (array)new CaseInsensitiveArray(array(

continuación, que acaba de obtener una matriz normal de PHP (is_array ($ bla) devuelve verdadero, y array_keys ($ bla) que funciona), pero toda la funcionalidad de la ArrayObject se pierde la subclase derivada (en este caso, las claves que no distinguen entre mayúsculas y minúsculas ya no funcionan). Intenta ejecutar el código anterior en ambos sentidos, y verás a qué me refiero.

PHP o bien debe proporcionar una variedad nativa en la que las teclas son sensibles a mayúsculas, o hacer ArrayObject ser convertible a la matriz sin perder la funcionalidad de los implementos cualquier subclase, o simplemente hacer todas las funciones de matriz aceptan casos ArrayObject.

Cuestiones relacionadas