2008-09-15 7 views
21

Je voudrais être capable d'écrire une classe PHP qui se comporte comme un tableau et qui utilise la syntaxe normale du tableau pour obtenir le paramètre &.Faire un objet PHP se comporter comme un tableau?

Par exemple (où Foo est une classe PHP de ma fabrication):

$foo = new Foo(); 

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

echo $foo['fooKey']; 

Je sais que PHP a le _get et _set méthodes magiques mais ceux qui ne vous permettent pas d'utiliser la notation de tableau pour accéder aux éléments. Python le gère en surchargeant __getitem__ et __setitem__.

Existe-t-il un moyen de le faire en PHP? Si cela fait une différence, je cours PHP 5.2.

Répondre

35

Si vous étendez ArrayObject ou implémentez ArrayAccess alors vous pouvez faire ce que vous voulez.

+0

Très cool. Il ne semble pas que l'un de ceux-ci puisse être utilisé avec des fonctions de tableau comme array_key_exists, etc. Est-ce correct? –

+0

Correct, utilisez la méthode offsetExist() à la place. –

+0

Est-ce que je ferais cela sur l'objet instancié lui-même? if ($ foo-> offsetExists ('fooKey')) {} –

2

Nope, coulée résultats seulement dans un tableau PHP normal - perdre toutes les fonctionnalités que votre classe dérivée ArrayObject-a. Vérifiez cela:

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"; 

Comme prévu, l'appel array_keys() échoue. De plus, is_array ($ blah) renvoie false. Mais si vous changez la ligne constructeur à:

$blah = (array)new CaseInsensitiveArray(array(

vous obtenez juste un tableau PHP normal (is_array ($ blah) retourne vrai, et array_keys ($ blah) fonctionne), mais toutes les fonctionnalités du ArrayObject La sous-classe -derived est perdue (dans ce cas, les clés insensibles à la casse ne fonctionnent plus). Essayez d'exécuter le code ci-dessus dans les deux sens, et vous verrez ce que je veux dire. PHP doit soit fournir un tableau natif dans lequel les clés sont insensibles à la casse, soit rendre ArrayObject castable en tableau sans perdre la fonctionnalité implémentée par la sous-classe, ou simplement faire en sorte que toutes les fonctions de tableau acceptent les instances ArrayObject.

Questions connexes