Pull to refresh

Обработка многомерных ассоциативных массивов 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.

Спасибо за внимание.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.