Массивы


На самом деле массив в PHP - это упорядоченное отображение, которое устанавливает соответствие между значением и ключом. Этот тип оптимизирован в нескольких направлениях, поэтому вы можете использовать его как собственно массив, список (вектор), хэш-таблицу (являющуюся реализацией карты), словарь, коллекцию, стэк, очередь и, возможно, что-то еще. Так как значением массива может быть другой массив PHP, можно также создавать деревья и многомерные массивы.

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

Синтаксис

Определение при помощи array()

Массив (тип array) может быть создан языковой конструкцией array(). language construct. В качестве параметров она принимает любое количество разделенных запятыми пар key => value (ключ => значение).

 array(     key  => value,     key2 => value2,     key3 => value3,     ... )

Запятая после последнего элемента массива необязательна и может быть опущена. Обычно это делается для однострочных массивов, т.е. array(1, 2) предпочтительней array(1, 2, ). Для многострочных массивов с другой стороны обычно используется завершающая запятая, так как позволяет легче добавлять новые элементы в конец массива.

Начиная с PHP 5.4 возможно использовать короткий синтаксис определения массивов, который заменяет языковую конструкцию array() на [].

Пример #1 Простой массив

<?php
$array 
= array(
    
"foo" => "bar",
    
"bar" => "foo",
);

// Начиная с PHP 5.4
$array = [
    
"foo" => "bar",
    
"bar" => "foo",
];
?>

key может быть либо типа integer, либо типа string. value может быть любого типа.

Дополнительно с ключом key будут сделаны следующие преобразования:

  • Строки, содержащие целое число будут преобразованы к типу integer. Например, ключ со значением "8" будет в действительности сохранен со значением 8. С другой стороны, значение "08" не будет преобразовано, так как оно не является корректным десятичным целым.
  • Числа с плавающей точкой (тип float) также будут преобразованы к типу integer, т.е. дробная часть будет отброшена. Например, ключ со значением 8.7 будет в действительности сохранен со значением 8.
  • Тип bool также преобразовываются к типу integer. Например, ключ со значением true будет сохранен со значением 1 и ключ со значением false будет сохранен со значением 0.
  • Тип null будет преобразован к пустой строке. Например, ключ со значением null будет в действительности сохранен со значением "".
  • Массивы (тип array) и объекты (тип object) не могут использоваться в качестве ключей. При подобном использовании будет генерироваться предупреждение: Недопустимый тип смещения (Illegal offset type).

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

Пример #2 Пример преобразования типов и перезаписи элементов

<?php
$array 
= array(
    
1    => "a",
    
"1"  => "b",
    
1.5  => "c",
    
true => "d",
);
var_dump($array);
?>

Результат выполнения данного примера:

 array(1) {   [1]=>   string(1) "d" } 

Так как все ключи в вышеприведенном примере преобразуются к 1, значение будет перезаписано на каждый новый элемент и останется только последнее присвоенное значение "d".

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

Пример #3 Смешанные ключи типов integer и string

<?php
$array 
= array(
    
"foo" => "bar",
    
"bar" => "foo",
    
100   => -100,
    -
100  => 100,
);
var_dump($array);
?>

Результат выполнения данного примера:

 array(4) {   ["foo"]=>   string(3) "bar"   ["bar"]=>   string(3) "foo"   [100]=>   int(-100)   [-100]=>   int(100) } 

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

Пример #4 Индексированные массивы без ключа

<?php
$array 
= array("foo""bar""hello""world");
var_dump($array);
?>

Результат выполнения данного примера:

 array(4) {   [0]=>   string(3) "foo"   [1]=>   string(3) "bar"   [2]=>   string(5) "hello"   [3]=>   string(5) "world" } 

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

Пример #5 Ключи для некоторых элементов

<?php
$array 
= array(
         
"a",
         
"b",
    
=> "c",
         
"d",
);
var_dump($array);
?>

Результат выполнения данного примера:

 array(4) {   [0]=>   string(1) "a"   [1]=>   string(1) "b"   [6]=>   string(1) "c"   [7]=>   string(1) "d" } 

Как вы видите последнее значение "d" было присвоено ключу 7. Это произошло потому, что самое большое значение ключа целого типа перед этим было 6.

Доступ к элементам массива с помощью квадратных скобок

Доступ к элементам массива может быть осуществлен с помощью синтаксиса array[key].

Пример #6 Доступ к элементам массива

<?php
$array 
= array(
    
"foo" => "bar",
    
42    => 24,
    
"multi" => array(
         
"dimensional" => array(
             
"array" => "foo"
         
)
    )
);

var_dump($array["foo"]);
var_dump($array[42]);
var_dump($array["multi"]["dimensional"]["array"]);
?>

Результат выполнения данного примера:

 string(3) "bar" int(24) string(3) "foo" 

Замечание:

Для доступа к элементам массива могут использоваться как квадратные, так и фигурные скобки (например, $array[42] и $array{42} означают одно и то же в вышеприведенном примере).

С PHP 5.4 стало возможным прямое разыменование массива, возвращаемого в качестве результата вызова функции или метода. Раньше приходилось использовать временные переменные.

С PHP 5.5 стало возможным прямое разыменование элементов у литерала массива.

Пример #7 Разыменование массива

<?php
function getArray() {
    return array(
123);
}

// в PHP 5.4
$secondElement getArray()[1];

// ранее делали так
$tmp getArray();
$secondElement $tmp[1];

// или так
list(, $secondElement) = getArray();
?>

Замечание:

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

Создание/модификация с помощью синтаксиса квадратных скобок

Существующий массив может быть изменен явной установкой значений в нем.

Это выполняется присвоением значений массиву array с указанием в скобках ключа. Кроме того, вы можете опустить ключ. В этом случае добавьте к имени переменной пустую пару скобок ([]).

     $arr[key] = value;     $arr[] = value;     // key может быть integer или string     // value может быть любым значением любого типа

Если массив $arr еще не существует, он будет создан. Таким образом, это еще один способ определить массив array. Однако такой способ применять не рекомендуется, так как если переменная $arr уже содержит некоторое значение (например, значение типа string из переменной запроса), то это значение останется на месте и [] может на самом деле означать доступ к символу в строке. Лучше инициализировать переменную путем явного присваивания значения.

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

<?php
$arr 
= array(=> 112 => 2);

$arr[] = 56;    // В этом месте скрипта это
                // то же самое, что и $arr[13] = 56;

$arr["x"] = 42// Это добавляет к массиву новый
                // элемент с ключом "x"
                
unset($arr[5]); // Это удаляет элемент из массива

unset($arr);    // Это удаляет массив полностью
?>

Замечание:

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

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

<?php
// Создаем простой массив.
$array = array(12345);
print_r($array);

// Теперь удаляем каждый элемент, но сам массив оставляем нетронутым:
foreach ($array as $i => $value) {
    unset(
$array[$i]);
}
print_r($array);

// Добавляем элемент (обратите внимание, что новым ключом будет 5, вместо 0).
$array[] = 6;
print_r($array);

// Переиндексация:
$array array_values($array);
$array[] = 7;
print_r($array);
?>

Результат выполнения данного примера:

 Array (     [0] => 1     [1] => 2     [2] => 3     [3] => 4     [4] => 5 ) Array ( ) Array (     [5] => 6 ) Array (     [0] => 6     [1] => 7 ) 

Полезные функции

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

Замечание:

Функция unset() позволяет удалять ключи массива. Обратите внимание, что массив НЕ будет переиндексирован. Если вы действительно хотите поведения в стиле "удалить и сдвинуть", можно переиндексировать массив используя array_values().

<?php
$a 
= array(=> 'один'=> 'два'=> 'три');
unset(
$a[2]);
/* даст массив, представленный так:
   $a = array(1 => 'один', 3 => 'три');
   а НЕ так:
   $a = array(1 => 'один', 2 => 'три');
*/

$b array_values($a);
// Теперь $b это array(0 => 'один', 1 => 'три')
?>

Управляющая конструкция foreach существует специально для массивов. Она предоставляет возможность легко пройтись по массиву.

Что можно и нельзя делать с массивами

Почему $foo[bar] неверно?

Всегда заключайте в кавычки строковый литерал в индексе ассоциативного массива. К примеру, пишите $foo['bar'], а не $foo[bar]. Но почему? Часто в старых скриптах можно встретить следующий синтаксис:

<?php
$foo
[bar] = 'враг';
echo 
$foo[bar];
// и т.д.
?>

This is wrong, but it works. The reason is that this code has an undefined constant (bar) rather than a string ('bar' - notice the quotes). PHP may in the future define constants which, unfortunately for such code, have the same name. It works because PHP automatically converts a bare string (an unquoted string which does not correspond to any known symbol) into a string which contains the bare string. For instance, if there is no defined constant named bar, then PHP will substitute in the string 'bar' and use that.

Замечание: Это не означает, что нужно всегда заключать ключ в кавычки. Нет необходимости заключать в кавычки константы или переменные, поскольку это помешает PHP обрабатывать их.

<?php
error_reporting
(E_ALL);
ini_set('display_errors'true);
ini_set('html_errors'false);
// Простой массив:
$array = array(12);
$count count($array);
for (
$i 0$i $count$i++) {
    echo 
"\nПроверяем $i: \n";
    echo 
"Плохо: " $array['$i'] . "\n";
    echo 
"Хорошо: " $array[$i] . "\n";
    echo 
"Плохо: {$array['$i']}\n";
    echo 
"Хорошо: {$array[$i]}\n";
}
?>

Результат выполнения данного примера:

 Проверяем 0: Notice: Undefined index:  $i in /path/to/script.html on line 9 Плохо: Хорошо: 1 Notice: Undefined index:  $i in /path/to/script.html on line 11 Плохо: Хорошо: 1  Проверяем 1: Notice: Undefined index:  $i in /path/to/script.html on line 9 Плохо: Хорошо: 2 Notice: Undefined index:  $i in /path/to/script.html on line 11 Плохо: Хорошо: 2 

Дополнительные примеры, демонстрирующие этот факт:

<?php
// Показываем все ошибки
error_reporting(E_ALL);

$arr = array('fruit' => 'apple''veggie' => 'carrot');

// Верно
print $arr['fruit'];  // apple
print $arr['veggie']; // carrot

// Неверно. Это работает, но из-за неопределенной константы с
// именем fruit также вызывает ошибку PHP уровня E_NOTICE
// 
// Notice: Use of undefined constant fruit - assumed 'fruit' in...
print $arr[fruit];    // apple

// Давайте определим константу, чтобы продемонстрировать, что
// происходит. Мы присвоим константе с именем fruit значение 'veggie'.
define('fruit''veggie');

// Теперь обратите внимание на разницу
print $arr['fruit'];  // apple
print $arr[fruit];    // carrot

// Внутри строки это нормально. Внутри строк константы не
// рассматриваются, так что ошибки E_NOTICE здесь не произойдет
print "Hello $arr[fruit]";      // Hello apple

// С одним исключением: фигурные скобки вокруг массивов внутри
// строк позволяют константам там находиться
print "Hello {$arr[fruit]}";    // Hello carrot
print "Hello {$arr['fruit']}";  // Hello apple

// Это не будет работать и вызовет ошибку обработки, такую как:
// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'
// Это, конечно, также действует и с суперглобальными переменными в строках
print "Hello $arr['fruit']";
print 
"Hello $_GET['foo']";

// Еще одна возможность - конкатенация
print "Hello " $arr['fruit']; // Hello apple
?>

Если вы переведете error_reporting в режим отображения ошибок уровня E_NOTICE (например, такой как E_ALL), вы сразу увидите эти ошибки. По умолчанию error_reporting установлена их не отображать.

Как указано в разделе синтаксис, внутри квадратных скобок ('[' и ']') должно быть выражение. Это означает, что можно писать вот так:

<?php
echo $arr[somefunc($bar)];
?>

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

<?php
$error_descriptions
[E_ERROR]   = "Произошла фатальная ошибка";
$error_descriptions[E_WARNING] = "PHP сообщает о предупреждении";
$error_descriptions[E_NOTICE]  = "Это лишь неофициальное замечание";
?>

Обратите внимание, что E_ERROR - это такой же верный идентификатор, как и bar в первом примере. Но последний пример по сути эквивалентен такой записи:

<?php
$error_descriptions
[1] = "Произошла фатальная ошибка";
$error_descriptions[2] = "PHP сообщает о предупреждении";
$error_descriptions[8] = "Это лишь неофициальное замечание";
?>

поскольку E_ERROR соответствует 1, и т.д.

Так что же в этом плохого?

Когда-нибудь в будущем, команда разработчиков PHP, возможно, пожелает добавить еще одну константу или ключевое слово, либо константа из другого кода может вмешаться и тогда у вас могут возникнуть проблемы. Например, вы уже не можете использовать таким образом слова empty и default, поскольку они являются зарезервированными ключевыми словами.

Замечание: Повторим, внутри строки (string), заключенной в двойные кавычки, корректно не окружать индексы массива кавычками, поэтому "$foo[bar]" является верной записью. Более подробно почему - смотрите вышеприведенные примеры, а также раздел обработка переменных в строках.

Преобразование в массив

Для любого из типов: integer, float, string, boolean и resource, преобразование значения в массив дает результатом массив с одним элементом (с индексом 0), являющимся скалярным значением, с которого вы начали. Другими словами, (array)$scalarValue - это точно то же самое, что и array($scalarValue).

Если вы преобразуете в массив объект (object), вы получите в качестве элементов массива свойства (переменные-члены) этого объекта. Ключами будут имена переменных-членов, с некоторыми примечательными исключениями: целочисленные свойства станут недоступны; к закрытым полям класса (private) спереди будет дописано имя класса; к защищенным полям класса (protected) спереди будет добавлен символ '*'. Эти добавленные значения с обоих сторон также имеют нулевые байты. Это может вызвать несколько неожиданное поведение:

<?php

class {
    private 
$A// Это станет '\0A\0A'
}

class 
extends {
    private 
$A// Это станет '\0B\0A'
    
public $AA// Это станет 'AA'
}

var_dump((array) new B());
?>

Вышеприведенный код покажет 2 ключа с именем 'AA', хотя один из них на самом деле имеет имя '\0A\0A'.

Если вы преобразуете в массив значение NULL, вы получите пустой массив.

Сравнение

Массивы можно сравнивать при помощи функции array_diff() и операторов массивов.

Примеры

The array type in PHP is very versatile. Here are some examples: Тип массив в PHP является очень гибким, вот несколько примеров:

<?php
// это
$a = array( 'color' => 'red',
            
'taste' => 'sweet',
            
'shape' => 'round',
            
'name'  => 'apple',
            
4        // ключом будет 0
          
);

$b = array('a''b''c');

// . . .полностью соответствует
$a = array();
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name']  = 'apple';
$a[]        = 4;        // ключом будет 0

$b = array();
$b[] = 'a';
$b[] = 'b';
$b[] = 'c';

// после выполнения этого кода, $a будет массивом
// array('color' => 'red', 'taste' => 'sweet', 'shape' => 'round', 
// 'name' => 'apple', 0 => 4), а $b будет
// array(0 => 'a', 1 => 'b', 2 => 'c'), или просто array('a', 'b', 'c').
?>

Пример #8 Использование array()

<?php
// Массив как карта (свойств)
$map = array( 'version'    => 4,
              
'OS'         => 'Linux',
              
'lang'       => 'english',
              
'short_tags' => true
            
);
            
// исключительно числовые ключи
$array = array( 7,
                
8,
                
0,
                
156,
                -
10
              
);
// это то же самое, что и array(0 => 7, 1 => 8, ...)

$switching = array(         10// ключ = 0
                    
5    =>  6,
                    
3    =>  7
                    
'a'  =>  4,
                            
11// ключ = 6 (максимальным числовым индексом было 5)
                    
'8'  =>  2// ключ = 8 (число!)
                    
'02' => 77// ключ = '02'
                    
0    => 12  // значение 10 будет перезаписано на 12
                  
);
                  
// пустой массив
$empty = array();         
?>

Пример #9 Коллекция

<?php
$colors 
= array('red''blue''green''yellow');

foreach (
$colors as $color) {
    echo 
"Вам нравится $color?\n";
}

?>

Результат выполнения данного примера:

 Вам нравится red? Вам нравится blue? Вам нравится green? Вам нравится yellow? 

Изменение значений массива напрямую стало возможным с версии PHP 5 путем передачи их по ссылке. До этого необходим следующий обходной прием:

Пример #10 Изменение элемента в цикле

<?php
// PHP 5
foreach ($colors as &$color) {
    
$color strtoupper($color);
}
unset(
$color); /* это нужно для того, чтобы последующие записи в
$color не меняли последний элемент массива */

// Обходной прием для старых версий
foreach ($colors as $key => $color) {
    
$colors[$key] = strtoupper($color);
}

print_r($colors);
?>

Результат выполнения данного примера:

 Array (     [0] => RED     [1] => BLUE     [2] => GREEN     [3] => YELLOW ) 

Следующий пример создает массив, начинающийся с единицы.

Пример #11 Индекс, начинающийся с единицы

<?php
$firstquarter  
= array(=> 'Январь''Февраль''Март');
print_r($firstquarter);
?>

Результат выполнения данного примера:

 Array  (     [1] => 'Январь'     [2] => 'Февраль'     [3] => 'Март' ) 

Пример #12 Заполнение массива

<?php
// заполняем массив всеми элементами из директории
$handle opendir('.');
while (
false !== ($file readdir($handle))) {
    
$files[] = $file;
}
closedir($handle); 
?>

Массивы упорядочены. Вы можете изменять порядок элементов, используя различные функции сортировки. Для дополнительной информации смотрите раздел функции для работы с массивами. Вы можете подсчитать количество элементов в массиве с помощью функции count().

Пример #13 Сортировка массива

<?php
sort
($files);
print_r($files);
?>

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

Пример #14 Рекурсивные и многомерные массивы

<?php
$fruits 
= array ( "фрукты"  => array ( "a" => "апельсин",
                                       
"b" => "банан",
                                       
"c" => "яблоко"
                                     
),
                  
"числа"   => array ( 1,
                                       
2,
                                       
3,
                                       
4,
                                       
5,
                                       
6
                                     
),
                  
"дырки"   => array (      "первая",
                                       
=> "вторая",
                                            
"третья"
                                     
)
                );

// Несколько примеров доступа к значениям предыдущего массива
echo $fruits["дырки"][5];    // напечатает "вторая"
echo $fruits["фрукты"]["a"]; // напечатает "апельсин"
unset($fruits["дырки"][0]);  // удалит "первая"

// Создаст новый многомерный массив
$juices["apple"]["green"] = "good"
?>

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

<?php
$arr1 
= array(23);
$arr2 $arr1;
$arr2[] = 4// $arr2 изменился,
             // $arr1 все еще array(2, 3)
             
$arr3 = &$arr1;
$arr3[] = 4// теперь $arr1 и $arr3 одинаковы
?>