PHP: Массивы

В этой главе:

  • Основные сведения о массивах

  • Создание массива

  • Преобразование индексов

  • Доступ к элементам массива

  • Добавление и удаление элементов массива

  • Обход массива в цикле

Массив (array) - это переменная специального типа, хранящая много элементов данных. Маcсив позволяет обратиться отдельно к любому из составляющих его элементов (поскольку внутри массива они хранятся отдельно), а также есть возможность копировать или обрабатывать массив целиком.

Массивы PHP нетипизированы, это означает, что элементы массива могут иметь любой тип, причем разные элементы в массиве могут иметь различные типы. Помимо этого массивы PHP являются динамическими, это означает, что фиксированный размер объявлять не нужно и новые элементы можно дабавлять в любое время.

Основные сведения о массивах

Чтобы работать с массивами, вам нужно освоить два новых понятия: элементы и индексы. Элементы - это значения хранящиеся в массиве, значения могут быть абсолютно любого типа. К каждому элементу можно обратиться по его уникальному индексу. В качестве индекса может использоваться целое число или строка.

Массивы можно разделить на два типа: индексные, у которых в качестве значения индекса используется только целое число и ассоциативные, где значением индекса может быть как строка так и число. Часто в ассоциативных массивах индекс называется: «ключ».

Индексные массивы обычно называют просто «массивами», а ассоциативные массивы - «хешами», «ассоциативными» или «словарями».

Создание массива

В PHP есть три способа создания массивов. Первый способ - это создание с помощью специальной функции array(). В качестве аргументов функция принимает любое количество пар ключ => значение (key => value) разделенных запятыми или просто значения, также разделяемые запятыми. Она возвращает массив, который можно присвоить переменной.

1
2
3
4
5
6
7
8
<?php
 
  // Создание массива с числовыми индексами 
  $weekdays = array('Понедельник','Вторник','Среда',
                    'Четверг','Пятница','Суббота',
                    'Воскресенье');
 
?>

Так как указывать ключ не обязательно, значения можно добавлять в массив без его указания. Если ключ не указывается, PHP будет использовать числовые индексы. По умолчанию элементы будут нумероваться, начиная с нуля. Массивы с числовыми индексами позволяют просто добавить элемент, а PHP автоматически будет использовать предыдущее наибольшее значение ключа типа integer, увеличенное на 1.

Также можно указывать ключ для отдельных элементов:

1
2
3
4
5
6
7
8
9
<?php
 
  $my_array = array( 'a',
                     'b',
                7 => 'c',
                     'd');
  var_dump($my_array);
 
?>

Запустив данный пример, вы можете заметить, что последний элемент ('d') был присвоен ключу 8. Так получилось, потому что самое большое значение ключа целого типа перед ним было 7.

Теперь рассмотрим создание аccоциативного массива с помощью функции array(). Ассоциативный массив записывается немного по другому: для добавления элемента используется формат ключ => значение.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
 
  // Создание ассоциативного массива 
  $shapes = array('Январь'   => '30',
                  'Февраль'  => '28/29 (29 бывает каждые четыре года)',
                  'Март'     => '31',
                  'Апрель'   => '30',
                  'Май'      => '31',
                  'Июнь'     => '30',
                  'Июль'     => '31',
                  'Август'   => '31',
                  'Сентябрь' => '30',
                  'Октябрь'  => '31',
                  'Ноябрь'   => '30',
                  'Декабрь'  => '31');
 
?>

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

Теперь рассмотрим второй способ создания массива: использование квадратных скобок [], вместо специальной функции array():

1
2
3
4
5
6
7
8
9
10
<?php
 
  $my_array = array('foo' => 'bar',
                    'bar' => 'foo');
 
  // другой способ создания массива
  $my_array = ['foo' => 'bar',
               'bar' => 'foo'];
 
?>

Разницы между этими массивами никакой нет, кроме различия в написании.

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

1
2
3
4
5
6
7
8
<?php
 
  $my_array = ['Солнце' => 'яркое',
               'колесо' => 'круглое',
                10      => 'дом',
                -5      =>  290];
 
?>

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

Третий способ создания массивов будет рассмотрен в разделе «Добавление и удаление элементов массива».

Преобразование индексов

Как упоминалось в самом начале главы, ключ может быть одним из двух типов: string или integer. Поэтому ключи несоответствующие одному из этих типов будут преобразованы:

  • Если в качестве ключа выступает строка, которая содержит число, то она будет преобразована к типу integer. Однако, если число является некорректным десятичным целым, например '09', то оно не будет преобразовано в тип integer.

  • Вещественное число (float), также будет преобразовано в integer - дробная часть в этом случае отбрасывается. Например, если значение ключа 5.4, оно будет интерпретировано как 5.

  • Булев тип (bool) также будет преобразован в integer. Например, если значение ключа true, то оно будет преобразовано в 1, а ключ со значением false соответственно будет преобразован в 0.

  • Если используется тип null, он будет преобразован в пустую строку.

  • Объекты и массивы не могут быть использованы в качестве ключей.

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

1
2
3
4
5
6
7
8
9
10
<?php
 
  $my_array = array( 1    => 'a',
                    '1'   => 'b'// ключи преобразуются в число 1
                     1.5  => 'c',
                     true => 'd');
                      
  var_dump($my_array);
 
?>

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

Доступ к элементам массива

Доступ к элементам массива осуществляется с помощью квадратных скобок в которых указывается индекс/ключ: array[index/key].

1
2
3
4
5
6
7
8
9
<?php
 
$my_array = array('Шоколад' => 'молочный',
                   2        => 'foo');
 
echo $my_array['Шоколад'], "<br>";
echo $my_array[2];
 
?>

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

1
2
3
4
5
6
7
8
9
<?php
 
  function foo() {
    return array(1, 'hello world!', 3);
  }
   
  echo foo()[1]; // => hello world!
 
?>

Данный пример показывает, что можно обращаться к индексу массива, возвращаемого в качестве результата вызова функции или метода.

Добавление и удаление элементов массива

Теперь, когда вы получили основные понятия о массивах, рассмотрим способы записи значений в массив. Существующий массив может быть изменен явной установкой в нем значений. Это выполняется с помощью присваивания значений массиву.

Операция присваивания значения элементу массива выглядит так же, как операция присваивания значения переменной, за исключением квадратных скобок ([]), которые добавляются после имени переменной массива. В квадратных скобках указывается индекс/ключ элемента. Если индекс/ключ не указан, PHP автоматически выберет наименьший незанятый числовой индекс.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
 
  $my_arr = array( 0 => 'ноль',
                   1 => 'один');
  
  $my_arr[2] = 'два';
  $my_arr[3] = 'три';
    
  var_dump($my_arr);
   
  // присваивание без указания индекса/ключа
  $my_arr[] = 'четыре';
  $my_arr[] = 'пять';
   
  echo "<br>";
  var_dump($my_arr);
 
?>

Для изменения определенного значения, нужно просто присвоить новое значение уже существующему элементу. Чтобы удалить какой-либо элемент массива с его индексом/ключом или удалить полностью сам массив, используется функция unset():

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
   
  $my_arr = array(10, 15, 20);
   
  $my_arr[0] = 'радуга'; // изменяем значение первого элемента
                 
  unset($my_arr[1]);     // Удаляем полностью второй элемент (ключ/значение) из массива
   
  var_dump($my_arr);
 
  unset($my_arr);           // Полностью удалили массив
 
?>

Примечание: как уже упоминалось выше, если элемент добавляется в массив без указания ключа, PHP автоматически будет использовать предыдущее наибольшее значение ключа типа integer, увеличенное на 1. Если целочисленных индексов в массиве еще нет, то ключом будет 0 (ноль).

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<?php
   
  // Создаем простой массив с числовыми индексами.
  $my_arr = array(1, 2, 3);
  print_r($my_arr);
 
  // Теперь удаляем все элементы, но сам массив оставляем нетронутым:
  unset($my_arr[0]);
  unset($my_arr[1]);
  unset($my_arr[2]);
   
  echo "<br>";
  print_r($my_arr);
 
  // Добавляем элемент (обратите внимание, что новым ключом будет 3, вместо 0).
  $my_arr[] = 6;
   
  echo "<br>";
  print_r($my_arr);
 
  // Делаем переиндексацию:
  $my_arr = array_values($my_arr);
  $my_arr[] = 7;
   
  echo "<br>";
  print_r($my_arr);
 
?>

В этом примере использовались две новые функции, print_r() и array_values(). Функция array_values() возвращает индексированный массив (заново индексирует возвращаемый массив числовыми индексами), а функция print_r работает наподобие var_dump, но выводит массивы в более удобочитаемом виде.

Теперь мы можем рассмотреть третий способ создания массивов:

1
2
3
4
5
6
7
8
9
10
11
<?php
   
  // следующая запись создает массив
  $weekdays[] = 'Понедельник';
  $weekdays[] = 'Вторник';
   
  // тоже самое, но с указанием индекса
  $weekdays[0] = 'Понедельник';
  $weekdays[1] = 'Понедельник';
 
?>

В примере был показан третий способ создания массива. Если массив $weekdays еще не был создан, то он будет создан. Однако такой вид создания массива не рекомендуется применять, так как если переменная $weekdays уже была ранее создана и содержит значение, это может привести к неожиданным результатам работы сценария.

Если у вас возникают сомнения по поводу того, является ли переменная массивом, воспользуйтесь функцией is_array. Например, проверку можно выполнить следующим образом:

1
2
3
4
5
6
7
8
9
10
<?php
   
  $yes = array('это', 'массив');
  echo is_array($yes) ? 'Массив' : 'Не массив';
  echo '<br>';
   
  $no = 'обычная строка';
  echo is_array($no) ? 'Массив' : 'Не массив';
 
?>

Обход массива в цикле

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

1
2
3
foreach ($array as $value) {
  инструкции
}

Цикл будет перебирать заданный массив - $array (вместо $array подставляется название массива). На каждой итерации значение текущего элемента присваивается переменной $value (можно указать любое другое имя переменной). Оператор цикла foreach очень удобен, поскольку сам выполняет обход и чтение всех элементов массива, пока не будет достигнут последний. Он позволяет не держать постоянно в памяти тот факт, что индексация массивов начинается с нуля, и никогда не выходит за пределы массива, что делает конструкцию цикла очень удобной и помогает избежать распространенных ошибок. Посмотрим, как он работает на примере:

1
2
3
4
5
6
7
8
9
<?php
   
  $my_arr = array(1, 2, 3, 4, 5);
   
  foreach ($my_arr as $value) {
    echo $value, " ";
}
 
?>

Второй вид синтаксиса foreach, выглядит так:

1
2
3
foreach ($array as $key => $value) {
  инструкции
}

При использовании данной формы синтаксиса на каждой итерации дополнительно присваивается значение текущего ключа переменной $key (можно указать любое другое имя переменной):

1
2
3
4
5
6
7
8
9
<?php
   
  $my_arr = array(1, 2, 3, 4, 5);
   
  foreach ($my_arr as $key => $value) {
    echo "[$key] => ", $value, "<br>";
}
 
?>

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

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php
   
  $my_arr = array(1, 2, 3);
  foreach ($my_arr as &$value) {
    $value *= 2;
    echo $value;
  }
   
  /* это нужно для того, чтобы последующие записи в
  переменную $value не меняли последний элемент массива */
  unset($value); // разорвать ссылку на последний элемент
 
?>

Примечание: Ссылка на последний элемент массива остается даже после того, как оператор foreach завершил работу. Поэтому рекомендуется удалять ее с помощью функции unset() как показано в примере выше. Давайте посмотрим что будет, если не использовать unset():

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
   
  $numbers = array(1,2,3,4,5);
    
  foreach ($numbers as &$num) {
    echo $num, " ";
  }
   
  // Присваиваем новое значение переменной $num
  $num = '100';
  echo '<br>';
  
  foreach ($numbers as &$num) {
    echo $num, " ";
  }
 
?>

Стоит отметить следующий момент, ссылку можно использовать только если перебираемый массив является переменной. Следующий код не будет работать:

1

2

3

4

5

6

7

<?php
   
  foreach (array(1, 2, 3) as &$value) {
    $value *= 2;
  }
 
?>