Итерация объекта ArrayObject
Проблема:
ArrayObject работает должным образом, когда значения задаются или считываются вручную, но при использовании функции (например, foreach) для ее повторения все становится плохо.
Он не вызывает методы offset*, которые я определил, но вместо этого использует методы ArrayIterator.
Код:
Класс:
class obsecureArray extends ArrayObject {
public function offsetSet($name, $value) {
call_user_func_array(array('parent', __FUNCTION__), array(base64_encode($name), base64_encode($value)) );
}
public function offsetGet($name) {
return base64_decode( call_user_func_array(array('parent', __FUNCTION__), (array) base64_encode($name) ) );
}
public function offsetExists($name) {
return call_user_func_array(array('parent', __FUNCTION__), (array) base64_encode($name) );
}
public function offsetUnset($name) {
return call_user_func_array(array('parent', __FUNCTION__), (array) base64_encode($name) );
}
}
Пример использования:
$a = new obsecureArray();
$a['test'] = 'Value';
$a[2] = '1';
define('BR','<br />');
echo 'test: ',$a['test'],BR,'2: ',$a[2],BR;
foreach($a as $key => $value)
echo 'Key: ',$key,' Value:',$value,BR;
Вывод:
test: Value
2: 1
Key: dGVzdA== Value:VmFsdWU=
Key: Mg== Value:MQ==
4 answers
Я заглядываю в Объект ArrayObject __construct
метод документация и нашел третий аргумент, связанный с моей проблемой:
Класс итератора:
Укажите класс, который будет использоваться для итерации объекта ArrayObject. ArrayIterator - это используемый класс по умолчанию.
Теперь я мог бы расширить ArrayIterator
с помощью моих собственных методов offset*
и передайте его моему конструктору ArrayObject
, поэтому я заглянул в ArrayIterator
, и это было почти идентичен ArrayObject
, за исключением того, что он явно не использовал внешний итератор. Так что все, что мне нужно было сделать, это расширить ArrayIterator
вместо этого. и также пришлось переопределить методы current
и key
.
Так что у меня есть:
class obsecureArray extends ArrayIterator {
public function offsetSet($name, $value) {
call_user_func_array(array('parent', __FUNCTION__), array(base64_encode($name), base64_encode($value)));
}
public function offsetGet($name) {
return base64_decode(call_user_func_array(array('parent', __FUNCTION__), (array) base64_encode($name)));
}
public function offsetExists($name) {
return call_user_func_array(array('parent', __FUNCTION__), (array) base64_encode($name));
}
public function offsetUnset($name) {
return call_user_func_array(array('parent', __FUNCTION__), (array) base64_encode($name));
}
public function key() {
return base64_decode(parent::key());
}
public function current() {
return base64_decode(parent::current());
}
}
И это работает отлично, как и ожидалось.
И для:
$a = new obsecureArray();
$a['test'] = 'Value';
$a[2] = '1';
define('BR','<br />');
echo 'test: ',$a['test'],BR,'2: ',$a[2],BR;
foreach($a as $key => $value)
echo 'Key: ',$key,' Value:',$value,BR;
Я получил:
test: Value 2: 1 Key: test Value:Value Key: 2 Value:1
Вы захотите реализовать Итератор или Итератораагрегат. У вас больше контроля над первым, но последнее проще реализовать (возможно, с большими накладными расходами):
class People implements IteratorAggregate {
protected $children;
// ...
public function getIterator() {
return new ArrayIterator( $this->children );
}
}
Смотрите Итератор для стандартных методов для этого интерфейса.
На мой взгляд, ваш код работает должным образом, если вы хотите убедиться, что ваши значения обрабатываются правильно, используйте правильные методы:
$a = new obsecureArray();
$a->offsetSet('test', 'Value');
$a->offsetSet(2, '1');
также вместо
define('BR','
');
Существует предопределенное свойство php PHP_EOL
Вам нужно будет установить пользовательский класс итератора:
<?php
class SecureArray extends ArrayObject {
public function __construct($array = array()) {
parent::__construct($array);
$this->setIteratorClass('SecureIterator');
}
public function offsetSet($name, $value) {
parent::offsetSet( base64_encode($name), base64_encode($value) );
}
public function offsetGet($name) {
return base64_decode( parent::offsetGet( base64_encode($name) ) );
}
public function offsetExists($name) {
return parent::offsetExists( base64_encode($name) );
}
public function offsetUnset($name) {
return parent::offsetUnset( base64_encode($name) );
}
}
class SecureIterator extends ArrayIterator {
function current() {
return base64_decode(parent::current());
}
function key() {
return base64_decode(parent::key());
}
}