Массивы
На самом деле массив в 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", "hallo", "world");
var_dump($array);
?>
Результат выполнения данного примера:
array(4) { [0]=> string(3) "foo" [1]=> string(3) "bar" [2]=> string(5) "hallo" [3]=> string(5) "world" }
Возможно указать ключ только для некоторых элементов и пропустить для других:
Пример #5 Ключи для некоторых элементов
<?php
$array = array(
"a",
"b",
6 => "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(1, 2, 3);
}
// в 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(5 => 1, 12 => 2);
$arr[] = 56; // В этом месте скрипта это
// то же самое, что и $arr[13] = 56;
$arr["x"] = 42; // Это добавляет к массиву новый
// элемент с ключом "x"
unset($arr[5]); // Это удаляет элемент из массива
unset($arr); // Это удаляет массив полностью
?>
Замечание:
Как уже говорилось выше, если ключ не был указан, то будет взят максимальный из существующих целочисленных (integer) индексов, и новым ключом будет это максимальное значение (в крайнем случае 0) плюс 1. Если целочисленных индексов еще нет, то ключом будет 0 (ноль).
Учтите, что максимальное целое значение ключа не обязательно существует в массиве в данный момент. Оно могло просто существовать в массиве какое-то время, с тех пор как он был переиндексирован в последний раз. Следующий пример это иллюстрирует:
<?php
// Создаем простой массив.
$array = array(1, 2, 3, 4, 5);
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(1 => 'один', 2 => 'два', 3 => 'три');
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];
// и т.д.
?>
Это неверно, хотя и работает. Причина
в том, что этот код содержит неопределенную константу (bar), а не
строку ('bar' - обратите внимание на кавычки), и PHP в будущем
может определить константу, которая, к несчастью для вашего кода,
будет иметь то же самое имя. Это работает, потому что PHP
автоматически преобразует "голую строку" (не
заключенную в кавычки строку, которая не соответствует ни одному
из известных символов языка) в строку, со значением этой "голой строки".
Например, если константа с именем bar
не
определена, то PHP заменит bar на строку 'bar' и
использует ее.
Замечание: Это не означает, что нужно всегда заключать ключ в кавычки. Нет необходимости заключать в кавычки константы или переменные, поскольку это помешает PHP обрабатывать их.
<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Простой массив:
$array = array(1, 2);
$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 A {
private $A; // Это станет '\0A\0A'
}
class B extends A {
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(1 => 'Январь', 'Февраль', 'Март');
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 ( "первая",
5 => "вторая",
"третья"
)
);
// Несколько примеров доступа к значениям предыдущего массива
echo $fruits["дырки"][5]; // напечатает "вторая"
echo $fruits["фрукты"]["a"]; // напечатает "апельсин"
unset($fruits["дырки"][0]); // удалит "первая"
// Создаст новый многомерный массив
$juices["apple"]["green"] = "good";
?>
Обратите внимание, что при присваивании массива всегда происходит копирование значения. Чтобы скопировать массив по ссылке, вам нужно использовать оператор ссылки.
<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 изменился,
// $arr1 все еще array(2, 3)
$arr3 = &$arr1;
$arr3[] = 4; // теперь $arr1 и $arr3 одинаковы
?>
Коментарии
Beware that if you're using strings as indices in the $_POST array, that periods are transformed into underscores:
<html>
<body>
<?php
printf("POST: "); print_r($_POST); printf("<br/>");
?>
<form method="post" action="<?php echo $_SERVER['PHP_SELF']; ?>">
<input type="hidden" name="Windows3.1" value="Sux">
<input type="submit" value="Click" />
</form>
</body>
</html>
Once you click on the button, the page displays the following:
POST: Array ( [Windows3_1] => Sux )
"If you convert a NULL value to an array, you get an empty array."
This turns out to be a useful property. Say you have a search function that returns an array of values on success or NULL if nothing found.
<?php $values = search(...); ?>
Now you want to merge the array with another array. What do we do if $values is NULL? No problem:
<?php $combined = array_merge((array)$values, $other); ?>
Voila.
please note that when arrays are copied, the "reference status" of their members is preserved (language.references.whatdo).
Note that array value buckets are reference-safe, even through serialization.
<?php
$x='initial';
$test=array('A'=>&$x,'B'=>&$x);
$test=unserialize(serialize($test));
$test['A']='changed';
echo $test['B']; // Outputs "changed"
?>
This can be useful in some cases, for example saving RAM within complex structures.
I think your first, main example is needlessly confusing, very confusing to newbies:
$array = array(
"foo" => "bar",
"bar" => "foo",
);
It should be removed.
For newbies:
An array index can be any string value, even a value that is also a value in the array.
The value of array["foo"] is "bar".
The value of array["bar"] is "foo"
The following expressions are both true:
$array["foo"] == "bar"
$array["bar"] == "foo"