Я бы хотел написать PHP-класс, который ведет себя как массив и использует обычный синтаксис массива для получения и настройки.
Например (где Foo – класс PHP для моего создания):
$foo = new Foo(); $foo['fooKey'] = 'foo value'; echo $foo['fooKey'];
Я знаю, что PHP имеет методы _get и _set magic, но они не позволяют использовать нотацию массива для доступа к элементам. 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.