ArrayObject итерация - PullRequest
       30

ArrayObject итерация

3 голосов
/ 11 января 2012

Проблема:

ArrayObject работает должным образом, когда значения устанавливаются или считываются вручную, но при использовании функции (например, foreach) для ее итерации все становится злым.

Он не вызывает методы смещения *, которые я определил, а вместо этого использует методы 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==

Пример CodePad.

Ответы [ 4 ]

3 голосов
/ 11 января 2012

Я изучаю ArrayObject __construct метод документация и нашел третий аргумент, связанный с моей проблемой:

iterator_class:

Укажите класс, который будет использоваться для итерации объекта 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

Пример CodePad

1 голос
/ 11 января 2012

Вы захотите реализовать Итератор или IteratorAggregate .Вы имеете больший контроль над первым, но последнее проще реализовать (возможно, с большими издержками):

class People implements IteratorAggregate {
    protected $children;

    // ...

    public function getIterator() {
        return new ArrayIterator( $this->children );
    }
}

См. Итератор для стандартных методов для этого интерфейса.

0 голосов
/ 11 января 2012

Вам необходимо установить собственный класс итератора:

<?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());
    }
}
0 голосов
/ 11 января 2012

По моему мнению, ваш код работает должным образом, если вы хотите убедиться, что ваши значения обрабатываются правильно, используйте правильные методы:

$a = new obsecureArray();
$a->offsetSet('test', 'Value');
$a->offsetSet(2, '1');

также вместо

define('BR','
');

есть предопределенное свойство php PHP_EOL

...