Заставить объект PHP вести себя как массив?
Вопрос
Я хотел бы иметь возможность написать класс PHP, который ведет себя как массив и использует обычный синтаксис массива для получения и установки.
Например (где Foo — это созданный мной класс PHP):
$foo = new Foo();
$foo['fooKey'] = 'foo value';
echo $foo['fooKey'];
Я знаю, что в PHP есть магические методы _get и _set, но они не позволяют использовать нотацию массива для доступа к элементам.Python справляется с этим, перегружая __getitem__ и __setitem__.
Есть ли способ сделать это в PHP?Если это имеет значение, я использую PHP 5.2.
Решение
Если вы продлите ArrayObject
или реализовать ArrayAccess
тогда ты можешь делать то, что хочешь.
Другие советы
Нет, приведение просто приводит к созданию обычного PHP-массива - при этом теряется вся функциональность вашего класса, производного от ArrayObject.Проверь это:
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";
Как и ожидалось, вызов array_keys() завершился неудачно.Кроме того, is_array($blah) возвращает false.Но если вы измените строку конструктора на:
$blah = (array)new CaseInsensitiveArray(array(
тогда вы просто получаете обычный массив PHP (is_array($blah) возвращает true, а array_keys($blah) работает), но вся функциональность подкласса, производного от ArrayObject, теряется (в этом случае регистронезависимые ключи больше не используются). работа).Попробуйте запустить приведенный выше код в обоих направлениях, и вы поймете, что я имею в виду.
PHP должен либо предоставить собственный массив, в котором ключи нечувствительны к регистру, либо сделать ArrayObject пригодным для приведения к массиву без потери каких-либо функций, реализуемых подклассом, либо просто заставить все функции массива принимать экземпляры ArrayObject.