PHP - массивы и несколько хитростей

PHP - массивы и несколько хитростей

PHP - массивы и несколько хитростейВ рамках данной статьи я расскажу вам несколько хитростей, которые можно применить при использовании массивов в PHP.

Как я уже говорил в одной из предыдущих статей про переменные переменных в PHP, этот язык предоставляет массу гибких и полезных возможностей, которые существенно облегчают творческий процесс написания кода. Однако, далеко не все о них знают. Поэтому сейчас я расскажу вам несколько хитростей про массивы.

Но, прежде, хотел бы сказать пару слов об объявлении массивов, так как начиная с PHP 5.4 появилась более короткая форма, а именно обычные квадратные скобки:

<?php
// Объявляем массив в 5.3
$some_array = array(...)
// Объявляем массив в 5.4
$some_array = [...]

Хоть эта форма выглядит более простой и привлекательной, ее бездумное использование может приводить к неожиданным ошибкам совместимости. Дело в том, что несмотря на то, что уже существует 7-я версия, достаточно много проектов и сайтов еще использует именно версию 5.3 (а порой и версии ниже). Поэтому настоятельно рекомендую пользоваться этим только в случае, если вы точно уверены, что ваш код будет запускаться на версии 5.4+.

Вероятно, вам может это показаться элементарным, но, к сожалению, на практике такие вещи периодически случаются. К примеру, вы можете узнать, что некая CMS, для которой заявлена поддержка 5.3, не устанавливается только потому, что один из ее модулей, включенных по умолчанию, как раз создает этот конфликт, так как использует конструкции из 5.4.

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

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

Быстрое преобразование массива в объект stdClass и обратно (плюс пара нюансов). Начну сразу с кода.

<?php
// Объявляем массив
$some_array = array('name' => 'some name', 'some_subarray' => array('id' => 1, 'test' => 'some data'));
echo '<br/>';
// Выводим
var_dump($some_array);
echo '<br/>';
// Теперь преобразуем в stdClass и выводим
// видим, что под массив не превратился в stdClass
$std_object = (object)$some_array;
var_dump($std_object);
echo '<br/>';
// Как видите, выводится Массив
var_dump($std_object->some_subarray);
echo '<br/>';
// А эта конструкция вернет NULL
var_dump($std_object->some_subarray->id);
echo '<br/>';
// Теперь, показываем, что выполняется и обратное преобразование
$some_array = (array)$std_object;
// Получили исходный массив
var_dump($some_array);
// Теперь напишем простую функцию для рекурсивную функцию для преобразования
function arrayObj($array) {
   if (isset($array) && is_array($array) && count($array) > 0) {
       foreach($array as $key => $value) {
           $array[$key] = arrayObj($value);
      }
      return (object)$array;
   }
   else if (isset($array) && !is_array($array)) {
      return $array;
   }
   else {
      return null;
   }
}
echo '<br/>';
// Получим рекурсивное преобразование
$std_object_rec = arrayObj($some_array);
var_dump($std_object_rec);
echo '<br/>';
// Как видите, выводится stdClass
var_dump($std_object_rec->some_subarray);
echo '<br/>';
// А эта конструкция вернет 1
var_dump($std_object_rec->some_subarray->id);
echo '<br/>';
echo '<br/>';
// Попробуем получить обратное преобразование и видим, что вложенный stdClass не преобразовался в массив
$some_array_rec = (array)$std_object_rec;
var_dump($some_array_rec);

Как вы можете сами убедиться, язык PHP поддерживает быстрое преобразование массивов в объекты класс stdClass и обратно. Однако, есть один важный нюанс. Дело в том, что происходит это только для первого уровня вложенности. Например, "some_subarray" так и останется массивом. В практике же бывает весьма выгодным делать именно полное преобразование, включая все вложенные массивы.

Однако, по умолчанию такой возможности в PHP нет, поэтому необходимо самим составить рекурсивный обход массива. В моем случае это функция "arrayObj". И как вы можете видеть, после ее использования тот же массив "some_subarray" был приведен к классу stdClass. И поэтому конструкция "$std_object_rec->some_subarray->id" вернет уже не NULL, а 1. Но, вместе с этим обычное преобразование объекта к массиву так же оставляет вложенный элемент "some_subarray" объектом. Поэтому если вам нужно полное преобразование объектов к многоуровневым массивам, то необходимо писать аналогичную рекурсивную функцию, только с проверкой "instanceof stdClass".

Примечание: Кстати, есть еще одна хитрость, в которой можно обойтись без рекурсивной функции это использование json_encode и json_decode - вначале преобразуете массив в json, а затем получаете полноценное преобразование в объект при декодировании json. Однако, такая операция является более нагрузочной. Поэтому если вам часто необходимо гонять данные из массива в объекты, то лучше воспользоваться функцией.

Перебор данных массива с помощью foreach. Ни для кого не секрет, что это весьма частая задача - перебрать данные и немного их подкорректировать. Поэтому опять же начну с кода.

<?php
// Создадим тестовый массив с данными
$some_array = array(
    'item1' => array('name' => 'data1', 'desc' => 'desc1'), 
    'item2' => array('name' => 'data2', 'desc' => 'desc2'),
    'item3' => array('name' => 'data3', 'desc' => 'desc3'),
);
echo '<br/>';echo '<br/>';
// Выводим исходный массив
var_dump($some_array);
// Теперь попробуем пройтись foreach и поменять данные в названии
foreach($some_array as $item) {
    $item['name'] = 'test';
}
echo '<br/>';echo '<br/>';
// Опять выводим массив и видим, что ничего не изменилось
// Так как $item представляет собой копию, а не исходный подмассив
var_dump($some_array);
// Теперь опять же воспользуемся foreach, но применим одну хитрость,
// а именно воспользуемся обращением через ссылку
foreach($some_array as &$item) {
    $item['name'] = 'test';
}
// Однако, в отличии от предыдущего варианта, стоит понимать, 
// что $item ссылается на реальный подмассив, 
// поэтому, чтобы случайно не переопределить данные в коде,
// после выхода из цикла необходимо переменную освободить
unset($item);
echo '<br/>';echo '<br/>';
// Опять выводим массив и видим, что теперь данные выставлены
var_dump($some_array);

В принципе, внутри кода есть все необходимые комментарии. Но, на всякий случай, хотел бы еще раз обратить ваше внимание, что после использования возможности получения элементов по ссылке в обязательном порядке необходимо использовать unset, в противном случае, использовав переменную $item хотя бы просто в другом цикле, вы можете столкнуться с ошибками, ведь будут модифицироваться исходные данные последнего элемента.

Как видите, в языке PHP есть масса полезных и гибких возможностей, применение которых может быть весьма полезным при создании своих шедевров.

Социальные сети

☕ Понравился обзор? Поделитесь с друзьями!

Комментарии / отзывы  

0 # Кодер 01.06.2017 13:38
Интересно было узнать про перебор через ссылку. Конечно, необходимость обнулять не очень-то удобно, но зато попробовал с массивами нескольких размерностей - удобно блин.
Ответить | Ответить с цитатой | Цитировать | Сообщить модератору
Добавить комментарий / отзыв
Комментарий - это вежливое и наполненное смыслом сообщение (правила).



* Нажимая на кнопку "Отправить", Вы соглашаетесь с политикой конфиденциальности.
Социальные сети
Программы (Freeware, OpenSource...)