Подтвердить что ты не робот

Создание объекта PHP ведет себя как массив?

Я бы хотел написать PHP-класс, который ведет себя как массив и использует обычный синтаксис массива для получения и настройки.

Например (где Foo - класс PHP моего создания):

$foo = new Foo();

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

echo $foo['fooKey'];

Я знаю, что PHP имеет методы _get и _set magic, но они не позволяют использовать нотацию массива для доступа к элементам. Python обрабатывает его, перегружая __getitem__ и __setitem __.

Есть ли способ сделать это в PHP? Если это имеет значение, я запускаю PHP 5.2.

4b9b3361

Ответ 1

Если вы расширяете ArrayObject или реализуете ArrayAccess, вы можете делать то, что хотите.

Ответ 2

Нет, кастинг просто приводит к нормальному массиву 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.