Класс dummyArray: как подружить код работающий с массивами и код работающий со свойствами объекта

в 22:29, , рубрики: array, class, php, wrapper, велосипед, массив, метки: , , , , ,

Возникла задача код работающий с набором данных как с массивом с кодом, который воспринимает этот же набор данных как класс.
Решение — создать класс с которым можно будет работать как с массивом (ArrayAccess), который будет также легко обходиться в foreach (Iterator) и у которого будут свойства с именами ключей. До кучи также был реализован интерфейс Countable.
Пример:

$user = new dummyArray;
// Добавим пару элементов в формате массива
$user['name'] = 'myname';
$user['sex'] = 'man';
// Добавим следующие пару записей в виде свойств объекта
$user->age = 18;
$user->occupation = 'director';


Класс правильно обходит любые ключи в итераторе (в отличии от примера в пхп-док, который работает только с последовательными цифровыми индексами). Фактически это просто сборка из нескольких примеров, с легкой косметикой.
Еще один пример:

// Создадим наш массив и проинициализируем его данными по умолчанию.
$a = new dummyArray('a','b','c','test','master');
// Добавим элемент как-будто мы работаем с массивом.
$a[99]='bla-bla-bla';
// текстовые ключи не вызывают проблем, впрочем также и на других языках
$a['text key']='other text';
// наш "массив" прекрасно воспринимается оператором foreach
foreach ($a as $key => $value) {
    echo $key.' => '.$value.'<br>';
}

Естественно к цифровым ключам не получить доступа через свойства.
Если в реальной реализации будет известно заранее список ключей, то можно инициализировать их из конструктора.

$b = new dummyArray;
// Добавим пару элементов в формате массива
$b['name'] = 'myname';
$b['phone'] = '1(234)567890';
$b['sex'] = 'man';
// Добавим следующие пару записей в виде свойств объекта
$b->age = 18;
$b->occupation = 'director';
// А теперь выведем наши параметры используя противоположные методы доступа :)
echo '<br><br>';
//
echo 'Name: '.$b->name.'<br>';
echo 'Phone: '.$b->phone.'<br>';
echo 'Sex: '.$b->sex.'<br>';
echo 'Admin: '.$b->name.'<br>';
//
echo 'Age: '.$b['age'].'<br>';
echo 'Occupation: '.$b['occupation'].'<br>';

Ну и собственно код класса:

class dummyArray  implements ArrayAccess, Iterator, Countable {
    private $container;
    private $position;
    //
    public function __construct() {
        $this->container = func_get_args();
        $this->rewind();
    }
    //
    public function offsetSet($offset, $value) {
        if (is_null($offset)) {
            $this->container[] = $value;
        } else {
            $this->container[$offset] = $value;
        }
    }
    public function offsetExists($offset) {
        return isset($this->container[$offset]);
    }
    public function offsetUnset($offset) {
        unset($this->container[$offset]);
    }
    public function offsetGet($offset) {
        return isset($this->container[$offset]) ? $this->container[$offset] : null;
    }
    //
    public function rewind() {
        reset($this->container);
        $this->position = key($this->container);
    }
    public function current() {
        return $this->container[$this->position];
    }
    public function key() {
        return $this->position;
    }
    public function next() {
        next($this->container);
        $this->position = key($this->container);
    }
    public function valid() {
        return isset($this->container[$this->position]);
    }
    //
    public function count() {
        return count($this->container);
    }
    //
    public function __get($name) {
        return $this->container[$name];
    }
    public function __set($name, $value) {
        $this->container[$name] = $value;
    }
}

Автор: Mendel


* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js