11111

Массивы

Пред.

Глава 11. Типы

След.

Массивы

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

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

Синтаксис

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

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

)

//key может быть integer или string

//value может быть любым значением

<?

$arr = array("foo" => "bar", 12 => true);

echo $arr["foo"]; //bar

echo $arr[12]; //1

?>

- key может быть либо integer, либо string. Если ключ - это стандартное представление integer, он так и будет интерпретироваться (т.е. "8" будет восприниматься как 8, тогда как "08" будет интерпретироваться как "08"). В PHP нет разницы между индексными и ассоциативными массивами; существует только 1 тип массива, который может содержать и числовые, и строковые индексы.

- Значение может быть любого имеющегося в PHP типа.

<?

$arr = array("somearray" => array(6 => 5, 13 => 9, "a" => 42));

echo $arr["somearray"][6]; //5

echo $arr["somearray"][13]; //9

echo $arr["somearray"]["a"]; //42

?>

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

<?

//Этот массив эквивалентен ...

array(5 => 43, 32, 56, "b" => 12);

//...этому массиву

array(5 => 43, 6 => 32, 7 => 56, "b" => 12);

?>

Внимание
- Начиная с PHP4.3.0, вышеописанное поведение генерации индекса изменено. Теперь, если вы будете использовать массив, в котором максимальным в настоящий момент является отрицательный ключ, то следующий созданный ключ будет нулевым (0). Раньше новым индексом становился самый большой существующий ключ + 1, так же как и у положительных индексов.

- Используя в качестве ключа TRUE вы получите ключ 1 типа integer. Используя в качестве ключа FALSE вы получите ключ 0 типа integer. Используя в качестве ключа NULL, вы получите пустую строку. Использование в качестве ключа пустой строки создаст (или перезапишет) ключ с пустой строкой и его значение; это не то же самое, что использование пустых квадратных скобок.

- Вы не можете использовать в качестве ключей массивы или объекты. Это вызовет предупреждение: Illegal offset type ('Недопустимый тип смещения').

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

- Также вы можете изменять существующий массив, явно устанавливая значения в нем.

- Это выполняется присвоением значений массиву при указании в скобках ключа. Кроме того, вы можете опустить ключ, в этом случае добавьте к имени переменной пустую пару скобок ("[]").
$arr[key] = value;

$arr[] = value;

//key может быть integer или string

//value может быть любым значением

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

<?

$arr = array(5 => 1, 12 => 2);

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

//эквивалентно $arr[13] = 56;

$arr["x"] = 42; //Это добавляет к массиву новый

//элемент с ключом "x"

unset($arr[5]); //Это удаляет элемент из массива

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

?>

Замечание: Как уже говорилось выше, если вы не укажите в скобках ключа, то будет взят максимальный из существующих целочисленных индексов, и новым ключом будет это максимальное значение + 1. Если целочисленных индексов еще нет, то ключом будет 0 (ноль). Если вы укажите ключ, которому уже присвоено значение, оно будет перезаписано.
Внимание
- Начиная с PHP4.3.0, вышеописанное поведение генерации индекса изменено. Теперь, если вы будете использовать массив, в котором максимальным в настоящий момент является отрицательный ключ, то следующий созданный ключ будет нулевым (0). Раньше новым индексом становился самый большой существующий ключ + 1, так же как и у положительных индексов.

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

<?

//Создаем простой массив.

$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().

<?

$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]. Но почему $foo[bar] это неверно? Возможно, вы встречали в старых скриптах следующий синтаксис:

<?

$foo[bar] = 'враг';

echo $foo[bar];

//и т. д.

?>

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

Замечание: Это не означает, что нужно всегда заключать ключ в кавычки. Нет необходимости заключать в кавычки константы или переменные, поскольку это помешает 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

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

<?

//Давайте покажем все ошибки

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 установлена их не отображать.

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

<?

echo $arr[somefunc($bar)];

?>

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

<?

$error_descriptions[E_ERROR] = "Произошла фатальная ошибка";

$error_descriptions[E_WARNING] = "PHP сообщает предупреждение";

$error_descriptions[E_NOTICE] = "Это лишь неофициальное замечание";

?>

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

<?

$error_descriptions[1] = "Произошла фатальная ошибка";

$error_descriptions[2] = "PHP сообщает предупреждение";

$error_descriptions[8] = "Это лишь неофициальное замечание";

?>

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

- Как мы уже объяснили в вышеприведенных примерах, $foo[bar] по-прежнему работает, но это неверно. Это работает, поскольку в соответствии со своим синтаксисом bar ожидается как константа. Однако, в данном случае константы с именем bar не существует. В таком случае PHP предполагает, что, написав bar, вы имели ввиду строку "bar", но забыли указать кавычки.

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

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

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

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

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

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

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

Сравнение

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

Примеры

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

<?

//это

$a = array( 'color' => 'red',

'taste' => 'sweet',

'shape' => 'round',

'name' => 'apple',

4 //ключом будет 0

);

//полностью соответствует

$a['color'] = 'red';

$a['taste'] = 'sweet';

$a['shape'] = 'round';

$a['name'] = 'apple';

$a[] = 4; //ключом будет 0

$b[] = 'a';

$b[] = 'b';

$b[] = 'c';

//создаст массив array(0 => 'a' , 1 => 'b' , 2 => 'c'),

//или просто array('a', 'b', 'c')

?>

Пример 11-4. Использование array()

<?

//Массив как карта (свойств)

$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();

?>

Пример 11-5. Коллекция

<?

$colors = array('красный', 'синий', 'зеленый', 'желтый');

foreach ($colors as $color) {

echo "Вам нравится $color?\n";

}

?>

Результат работы приведенного скрипта будет следующий:
Вам нравится красный?

Вам нравится синий?

Вам нравится зеленый?

Вам нравится желтый?

- Обратите внимание, что в настоящее время невозможно изменять значения массива в таком цикле напрямую.

Однако можно сделать так:

Пример 11-6. Коллекция

<?

foreach ($colors as $key => $color) {

//не будет работать:

//$color = strtoupper($color);

//работает:

$colors[$key] = strtoupper($color);

}

print_r($colors);

?>

Результат работы приведенного скрипта будет следующий:
Array

( [0] => КРАСНЫЙ [1] => СИНИЙ [2] => ЗЕЛЕНЫЙ [3] => ЖЕЛТЫЙ

)

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

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

<?

$firstquarter = array(1 => 'Январь', 'Февраль', 'Март');

print_r($firstquarter);

?>

Результат работы приведенного скрипта будет следующий:
Array

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

)

Пример 11-8. Заполнение массива

<?

//заполняет массив всеми элементами директории

$handle = opendir('.');

while (false !== ($file = readdir($handle))) {

$files[] = $file;

}

closedir($handle);

?>

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

Пример 11-9. Сортировка массива

<?

sort($files);

print_r($files);

?>

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

Пример 11-10. Рекурсивные и многомерные массивы

<?

$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["яблоко"]["зеленое"] = "хорошее";

?>

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

<?

$arr1 = array(2, 3);

$arr2 = $arr1;

$arr2[] = 4; //$arr2 изменился,

//$arr1 по прежнему array(2,3)

$arr3 = &$arr1;

$arr3[] = 4; //теперь $arr1 и $arr3 эквивалентны

?>

Пред.

Начало

След.

Строки

Уровень выше

Объекты 22222

Free Web Hosting