Как стать автором
Обновить

Обработка многомерных ассоциативных массивов PHP

Доброго времени суток, хабражители!

В своей статье я хочу поговорить об обработке многомерных ассоциативных массивов в PHP. На мой взгляд, не всегда удобно получать необходимую информацию из многомерного массива. Одно дело если массив двумерный:

<?
$array = array(
    "dimension1" => array(
        "key1" => "value1",
        "key2" => "value2"
    )
);
?>


То, конечно, получить, интересующие нас значения, легко:

echo $array['dimension1']['key1']; // value1


Но, а если мы имеем массив n-мерный? Например, пятимерный:

$array = array(
    'dimension1' => array(
        'dimension2' => array(
            'dimension3' => array(
                'dimension4' => array(
                    'dimension5' => array(
                        'value1' => 'Hey! I\'m value1',
                        'value2' => 'Hey! I\'m value2'
                    )
                )
            )
        )
    )
);


То, чтобы получить значение по ключу, например, «value1», нам надо прописать такой код:

echo $array["dimension1"]["dimension2"]["dimension3"]["dimension4"]["dimension5"]["value1"]; // Hey! I'm value1


Я такую запись не назвал бы красивой, хотя она является правильной. Я предлагаю слегка сделать эту запись красивой путем приведения ее к такому виду:

echo easyA($array)->dimension1->dimension2->dimension3->dimension4->dimension5->value1; // Hey! I'm value1


Согласитесь, ведь смотрится, действительно, куда симпотичней, по сравнению со стандартной записью.

Итак, для начала нам понадобится создать класс, который будет обрабатывать наш массив. Назовем его easyArray и сделаем его одиночкой (Singleton):

Код
class easyArray{
    private static $instance; // Состояние класса.
    private $Array; // Массив, который был передан классу.

    private function __construct(){
        // Запилили конструктор.
    }

    private function __clone(){
        // Запилили метод клонирования.
    }

    public static function getInstance(){
        if(null === self::$instance){
            self::$instance = new self();
        }
        return self::$instance;
    }



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

Код
    public function loadArray($newArray){
        if(is_array($newArray)){
            $this->Array = $newArray;
            
            return $this;
        }else{
            $error = 'К сожалению вы передали не массив.';
            throw new Exception($error);
        }
    }

Из кода видно, что мы также осуществляем проверку того, что было передано на вход метода. В случае того, если был передан все-таки не массив, мы просто выбросим исключение с ошибкой "К сожалению вы передали не массив.". Если проверка прошла успешно, то мы записываем в приватную переменную полученный массив и возвращаем текущий объект.


Ну а теперь мы переопределим магический метод "__get()" нашего класса. Это необходимо для того, чтобы получить желаемый нами результат. Итак:
Код
    public function __get($index){
        if(isset($this->Array[$index])){
            if(is_array($this->Array[$index])){
                $this->loadArray($this->Array[$index]);
                
                return $this;
            }else{
                return $this->Array[$index];
            }
        }else{
            $error = 'Отсутствует ключ ('.$index.') в массиве';
            throw new Exception($error);
        }
    }


Первым делом, мы проверяем наличие запрошенного ключа в массиве, в случае отсутствия такового, выбрасываем исключение с ошибкой "'Отсутствует ключ ('.$index.') в массиве'". Далее проверяем является ли, запрошенный ключ массивом. Если по такому ключу в массиве находится значение, то просто возвращаем это значение. А если все-таки это массив, то мы отправляем его методу "loadArray($newArray)" и возвращаем текущий объект ($this).


И, как последний штрих нашего класса, добавим метод, который будет возвращать текущий массив, с которым работает наш класс:
Код
    public function arrayReturn(){
        return $this->Array;
    }



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

echo easyArray::getInstance()->loadArray($array)->dimension1->dimension2->dimension3->dimension4->dimension5->value1;  // Hey! I'm value1


Стало даже длиннее, чем было. Но эта проблема решаема, и для этого нам понадобится простая функция:

function easyA($newArray){
    return easyArray::getInstance()->loadArray($newArray);
}


Ну, а теперь проверим, что мы получили в итоге:
Код
<?
$array = array(
    'dimension1' => array(
        'dimension2' => array(
            'dimension3' => array(
                'dimension4' => array(
                    'dimension5' => array(
                        'value1' => 'Hey! I\'m value1',
                        'value2' => 'Hey! I\'m value2'
                    )
                )
            )
        )
    )
);

require_once('easyArray.php');
require_once('easyArrayFunction.php');

echo easyA($array)->dimension1->dimension2->dimension3->dimension4->dimension5->value1; // Hey! I\'m value1
echo easyA($array)->dimension1->dimension2->dimension3->dimension4->dimension5->value2; // Hey! I\'m value2
?>

Все работает, как и задумывалось.


Помимо этого, данному классу можно передавать конфигурационные файлы типа:
Код
<?
return array(
    'dimension1' => array(
        'dimension2' => array(
            'dimension3' => array(
                'dimension4' => array(
                    'dimension5' => array(
                        'value1' => 'Hey! I\'m value1 from file array.php',
                        'value2' => 'Hey! I\'m value2 from file array.php'
                    )
                )
            )
        )
    )
);
?>


Для этого необходимо использовать такую конструкцию:
Код
echo easyA(require_once('array.php'))->dimension1->dimension2->dimension3->dimension4->dimension5->value1; // Hey! I'm value1 from file array.php



Возможно я изобрел велосипед, но я думаю, что данная статья будет интересна, как новичкам, так и остальным программистам.

Ссылки на файлы:
Файлы на GitHub.

Спасибо за внимание.
Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.