Arrays

Оновлено: 12.05.2023

Масив в PHP - це фактично впорядкована карта. Карта - це тип, який пов'язує значення з ключами. Цей тип оптимізовано для кількох різних застосувань; його можна розглядати як масив, список (вектор), хеш-таблицю (реалізацію карти), словник, колекцію, стек, чергу і, ймовірно, багато іншого. Оскільки значеннями масиву можуть бути інші масиви, можливі також дерева та багатовимірні масиви.

Пояснення цих структур даних виходить за рамки цього посібника, але для кожної з них наведено принаймні один приклад. Для отримання додаткової інформації зверніться до великої кількості літератури, яка існує на цю широку тему.

Масив можна створити за допомогою мовної конструкції array(). Вона приймає в якості аргументів довільну кількість пар ключ => значення, розділених комами.

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

Зауважте:

Існує синтаксис короткого масиву, який замінює array() на [].

Приклад #1 Простий масив

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

// Using the short array syntax
$array = [
    "foo" => "bar",
    "bar" => "foo",
];
?>

Ключ може бути як цілим числом, так і рядком. Значення може бути будь-якого типу.

Додатково відбудуться наступний кастинг ключів:

  • Рядки, що містять дійсні десяткові числа, якщо перед числом не стоїть знак +, будуть приведені до типу int. Наприклад, ключ "8" буде фактично збережено під номером 8. З іншого боку, "08" не буде приведено до типу int, оскільки воно не є дійсним десятковим цілим числом.
  • Числа з плаваючою комою також приводяться до цілих чисел, що означає, що дробова частина буде відкинута. Наприклад, ключ 8.7 насправді буде зберігатися під 8.
  • Були також приводяться до цілих чисел, тобто ключ true фактично буде зберігатися під 1, а ключ false - під 0.
  • Null буде приведено до порожнього рядка, тобто ключ null буде зберігатися під "".
  • Масиви та об'єкти не можна використовувати як ключі. Це призведе до видачі попередження: Неприпустимий тип зсуву.

Якщо декілька елементів в оголошенні масиву використовують один і той самий ключ, то буде використано лише останній, а всі інші будуть перезаписані.

Приклад #2 Приклад приведення та перезапису типів

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

Оскільки всі ключі у наведеному вище прикладі прирівнюються до 1, значення буде перезаписано для кожного нового елемента, і останнє присвоєне значення "d" буде єдиним, що залишиться.

Масиви PHP можуть містити ключі типу int і рядкові ключі одночасно, оскільки PHP не розрізняє індексовані та асоціативні масиви.

Приклад #3 Змішані int та рядкові ключі

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

Ключ не є обов'язковим. Якщо його не вказано, PHP використовуватиме приріст найбільшого раніше використаного ключа типу int.

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

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

Ви можете вказати ключ тільки для деяких елементів і не вказувати його для інших:

Приклад #5 Ключі не на всіх елементах

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

Приклад #6 Приклад складного приведення та перезапису типів

Цей приклад включає всі варіації приведення типів ключів і перезапису елементів.

<?php
$array = array(
    1    => 'a',
    '1'  => 'b', // the value "a" will be overwritten by "b"
    1.5  => 'c', // the value "b" will be overwritten by "c"
    -1 => 'd',
    '01'  => 'e', // as this is not an integer string it will NOT override the key for 1
    '1.5' => 'f', // as this is not an integer string it will NOT override the key for 1
    true => 'g', // the value "c" will be overwritten by "g"
    false => 'h',
    '' => 'i',
    null => 'j', // the value "i" will be overwritten by "j"
    'k', // value "k" is assigned the key 2. This is because the largest integer key before that was 1
    2 => 'l', // the value "k" will be overwritten by "l"
);

var_dump($array);
?>

Доступ до елементів масиву здійснюється за допомогою синтаксису array[key].

Приклад #7 Доступ до елементів масиву

<?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"]);
?>

Зауважте:

До версії PHP 8.0.0 для доступу до елементів масиву можна було взаємозамінно використовувати квадратні та фігурні дужки (наприклад, $array[42] та $array{42} у наведеному вище прикладі виконують одне й те саме). Синтаксис фігурних дужок було застаріло починаючи з версії PHP 7.4.0 і більше не підтримується починаючи з версії PHP 8.0.0.

Приклад #8 Розеременування масиву

<?php
function getArray() {
    return array(1, 2, 3);
}

$secondElement = getArray()[1];
?>

Зауважте:

Спроба отримати доступ до невизначеного ключа масиву - це те саме, що отримати доступ до будь-якої іншої невизначеної змінної: буде видано повідомлення про помилку рівня E_WARNING (до версії PHP 8.0.0 - E_NOTICE), а результат буде рівний нулю.

Зауважте:

Звільнення масиву від скалярного значення, яке не є рядком, повертає нуль. До версії PHP 7.4.0 це не призводило до появи повідомлення про помилку. Починаючи з PHP 7.4.0, це призводить до появи повідомлення E_NOTICE; починаючи з PHP 8.0.0, це призводить до появи повідомлення E_WARNING.

Існуючий масив можна модифікувати, явно задаючи в ньому значення.

Це робиться шляхом присвоєння значень масиву, вказуючи ключ у дужках. Ключ також можна не вказувати, у результаті чого залишиться порожня пара дужок ([]).

Якщо $arr ще не існує або має значення null чи false, його буде створено, тому це також альтернативний спосіб створення масиву. Однак не рекомендується так робити, оскільки якщо $arr вже містить деяке значення (наприклад, рядок зі змінної запиту), то це значення залишиться на цьому місці, а [] може означати оператор доступу до рядка. Завжди краще ініціалізувати змінну прямим присвоюванням.

Зауваження: Починаючи з версії PHP 7.1.0, застосування оператора порожнього індексу до рядка призводить до фатальної помилки. Раніше рядок мовчки перетворювався на масив.

Примітка: Починаючи з версії PHP 8.1.0, створення нового масиву зі значення false застаріло. Створення нового масиву з нульових та невизначених значень все ще дозволено.

Щоб змінити певне значення, присвойте цьому елементу нове значення за допомогою його ключа. Щоб видалити пару ключ/значення, викличте для неї функцію unset().

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

$arr[] = 56;    // This is the same as $arr[13] = 56;
                // at this point of the script

$arr["x"] = 42; // This adds a new element to
                // the array with key "x"
                
unset($arr[5]); // This removes the element from the array

unset($arr);    // This deletes the whole array
?>

Зауважте:

Як згадувалося вище, якщо ключ не вказано, береться максимальний з існуючих індексів int, і новим ключем буде це максимальне значення плюс 1 (але принаймні 0). Якщо індексів int ще не існує, ключем буде 0 (нуль).

Зверніть увагу, що максимальний цілочисельний ключ, який використовується для цього, не повинен існувати у масиві на даний момент. Він має існувати у масиві лише з моменту останньої переіндексації масиву. Наступний приклад ілюструє це:

<?php
// Create a simple array.
$array = array(1, 2, 3, 4, 5);
print_r($array);

// Now delete every item, but leave the array itself intact:
foreach ($array as $i => $value) {
    unset($array[$i]);
}
print_r($array);

// Append an item (note that the new key is 5, instead of 0).
$array[] = 6;
print_r($array);

// Re-index:
$array = array_values($array);
$array[] = 7;
print_r($array);
?>

Масиви можна деструктурувати за допомогою мовних конструкцій [] (починаючи з PHP 7.1.0) або list(). Ці конструкції можна використовувати для розбиття масиву на окремі змінні.

<?php
$source_array = ['foo', 'bar', 'baz'];

[$foo, $bar, $baz] = $source_array;

echo $foo;    // prints "foo"
echo $bar;    // prints "bar"
echo $baz;    // prints "baz"
?>

Деструктуризація масивів може бути використана у foreach для деструктуризації багатовимірного масиву під час ітерації над ним.

<?php
$source_array = [
    [1, 'John'],
    [2, 'Jane'],
];

foreach ($source_array as [$id, $name]) {
    // logic here with $id and $name
}
?>

Елементи масиву будуть проігноровані, якщо змінна не вказана. Деструктуризація масиву завжди починається з індексу 0.

<?php
$source_array = ['foo', 'bar', 'baz'];

// Assign the element at index 2 to the variable $baz
[, , $baz] = $source_array;

echo $baz;    // prints "baz"
?>

Починаючи з версії PHP 7.1.0, асоціативні масиви також можна деструктурувати. Це також полегшує вибір потрібного елемента в масивах з числовою індексацією, оскільки індекс можна вказати явно.

<?php
$source_array = ['foo' => 1, 'bar' => 2, 'baz' => 3];

// Assign the element at index 'baz' to the variable $three
['baz' => $three] = $source_array;

echo $three;    // prints 3

$source_array = ['foo', 'bar', 'baz'];

// Assign the element at index 2 to the variable $baz
[2 => $baz] = $source_array;

echo $baz;    // prints "baz"
?>

Деструктуризація масивів може бути використана для легкої заміни двох змінних.

<?php
$a = 1;
$b = 2;

[$b, $a] = [$a, $b];

echo $a;    // prints 2
echo $b;    // prints 1
?>

Зауважте:

Оператор поширення (...) не підтримується у присвоєннях.

Зауважте:

Спроба отримати доступ до невизначеного ключа масиву - це те саме, що отримати доступ до будь-якої іншої невизначеної змінної: буде видано повідомлення про помилку рівня E_WARNING (до версії PHP 8.0.0 - E_NOTICE), а результат буде рівний нулю.

Існує досить багато корисних функцій для роботи з масивами. Див. розділ Функції роботи з масивами.

Зауважте:

Функція unset() дозволяє видаляти ключі з масиву. Зверніть увагу, що масив не буде переіндексовано. Якщо ви бажаєте отримати справжню поведінку "видалити і зсунути", масив можна переіндексувати за допомогою функції array_values().

<?php
$a = array(1 => 'one', 2 => 'two', 3 => 'three');
unset($a[2]);
/* will produce an array that would have been defined as
   $a = array(1 => 'one', 3 => 'three');
   and NOT
   $a = array(1 => 'one', 2 =>'three');
*/

$b = array_values($a);
// Now $b is array(0 => 'one', 1 =>'three')
?>

Структура управління foreach існує спеціально для масивів. Вона забезпечує простий спосіб обходу масиву.

Завжди використовуйте лапки навколо індексу масиву рядкових літералів. Наприклад, $foo['bar'] є правильним, а $foo[bar] - ні. Але чому? Такий синтаксис часто зустрічається в старих скриптах:

<?php
$foo[bar] = 'enemy';
echo $foo[bar];
// etc
?>

Це неправильно, але працює. Причина в тому, що цей код має невизначену константу (bar), а не рядок ("bar" - зверніть увагу на лапки). Це працює тому, що PHP автоматично перетворює порожній рядок (рядок без лапок, який не відповідає жодному відомому символу) у рядок, який містить порожній рядок. Наприклад, якщо немає визначеної константи з іменем bar, то PHP підставить замість неї рядок 'bar' і використає його.

Обробка невизначеної константи як порожнього рядка призводить до помилки рівня E_NOTICE. Починаючи з версії PHP 7.2.0, цю помилку було застаріло, і вона призводить до помилки рівня E_WARNING. Починаючи з версії PHP 8.0.0, її було вилучено і вона генерує виключення Error.

Зауваження: Це не означає, що ключ завжди слід брати в лапки. Не беріть у лапки ключі, які є константами або змінними, оскільки це завадить PHP інтерпретувати їх.

<?php
error_reporting(E_ALL);
ini_set('display_errors', true);
ini_set('html_errors', false);
// Simple array:
$array = array(1, 2);
$count = count($array);
for ($i = 0; $i < $count; $i++) {
    echo "\nChecking $i: \n";
    echo "Bad: " . $array['$i'] . "\n";
    echo "Good: " . $array[$i] . "\n";
    echo "Bad: {$array['$i']}\n";
    echo "Good: {$array[$i]}\n";
}
?>

Якщо error_reporting налаштовано на показ помилок рівня E_NOTICE (наприклад, встановивши значення E_ALL), такі використання стануть одразу помітними. За замовчуванням error_reporting налаштовано так, щоб не показувати повідомлення.

Як зазначено у розділі синтаксису, те, що знаходиться у квадратних дужках ('[' та ']'), має бути виразом. Це означає, що такий код працює:

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

Це приклад використання значення, що повертається функцією, як індексу масиву. PHP також знає про константи:

<?php
$error_descriptions[E_ERROR]   = "A fatal error has occurred";
$error_descriptions[E_WARNING] = "PHP issued a warning";
$error_descriptions[E_NOTICE]  = "This is just an informal notice";
?>

Зверніть увагу, що E_ERROR також є допустимим ідентифікатором, як і bar у першому прикладі. Але останній приклад фактично збігається з написанням:

<?php
$error_descriptions[1] = "A fatal error has occurred";
$error_descriptions[2] = "PHP issued a warning";
$error_descriptions[8] = "This is just an informal notice";
?>

тому що E_ERROR дорівнює 1 і т.д.

В якийсь момент в майбутньому команда PHP може захотіти додати ще одну константу або ключове слово, або константа в іншому коді може заважати. Наприклад, слова empty і default вже неправильно використовувати таким чином, оскільки вони є зарезервованими ключовими словами.

Зауваження: Повторюємо, що всередині рядка у подвійних лапках можна не брати індекси масиву у лапки, тому "$foo[bar]" буде коректним. Дивіться наведені вище приклади, щоб дізнатися чому, а також розділ про розбір змінних у рядках.

Для будь-якого з типів int, float, string, bool і resource перетворення значення в масив призводить до створення масиву з єдиним елементом з нульовим індексом і значенням скаляра, який було перетворено. Іншими словами, (array)$scalarValue - це те саме, що і array($scalarValue).

Якщо об'єкт перетворюється на масив, результатом є масив, елементами якого є властивості об'єкта. Ключами є імена змінних-членів, за кількома важливими винятками: цілочисельні властивості недоступні; приватні змінні мають ім'я класу, що додається до імені змінної; захищені змінні мають символ '*', що додається до імені змінної. Ці додані значення мають NULL байт з обох боків. Неініціалізовані типізовані властивості автоматично відкидаються.

<?php

class A {
    private $B;
    protected $C;
    public $D;
    function __construct()
    {
        $this->{1} = null;
    }
}

var_export((array) new A());
?>

Ці NUL можуть призвести до неочікуваної поведінки:

<?php

class A {
    private $A; // This will become '\0A\0A'
}

class B extends A {
    private $A; // This will become '\0B\0A'
    public $AA; // This will become 'AA'
}

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

У наведеному вище прикладі буде показано два ключі з іменем 'AA', хоча насправді один з них має ім'я '\0A\0A'.

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

Порівнювати масиви можна за допомогою функції array_diff() та операторів над масивами.

Масив з префіксом ... буде розширено на місці під час визначення масиву. Тільки масиви та об'єкти, які реалізують Traversable, можуть бути розгорнуті. Розпакування масивів за допомогою ... доступне починаючи з версії PHP 7.4.0.

Можна багаторазово розширювати і додавати звичайні елементи до або після оператора ...:

Приклад #9 Просте розпакування масиву

<?php
// Using short array syntax.
// Also, works with array() syntax.
$arr1 = [1, 2, 3];
$arr2 = [...$arr1]; //[1, 2, 3]
$arr3 = [0, ...$arr1]; //[0, 1, 2, 3]
$arr4 = [...$arr1, ...$arr2, 111]; //[1, 2, 3, 1, 2, 3, 111]
$arr5 = [...$arr1, ...$arr1]; //[1, 2, 3, 1, 2, 3]

function getArr() {
  return ['a', 'b'];
}
$arr6 = [...getArr(), 'c' => 'd']; //['a', 'b', 'c' => 'd']
?>

Розпакування масиву оператором ... відбувається за семантикою функції array_merge(). Тобто, більш пізні рядкові ключі перезаписують більш ранні, а цілочисельні ключі перенумеровуються:

Приклад #10 Розпакування масиву з дублікатом ключа

<?php
// string key
$arr1 = ["a" => 1];
$arr2 = ["a" => 2];
$arr3 = ["a" => 0, ...$arr1, ...$arr2];
var_dump($arr3); // ["a" => 2]

// integer key
$arr4 = [1, 2, 3];
$arr5 = [4, 5, 6];
$arr6 = [...$arr4, ...$arr5];
var_dump($arr6); // [1, 2, 3, 4, 5, 6]
// Which is [0 => 1, 1 => 2, 2 => 3, 3 => 4, 4 => 5, 5 => 6]
// where the original integer keys have not been retained.
?>

Зауважте:

Ключі, які не є ані цілими числами, ані рядками, спричиняють TypeError. Такі ключі можуть бути згенеровані тільки об'єктом Traversable.

Зауважте:

До версії PHP 8.1 розпакування масиву з рядковим ключем не підтримується:

<?php

$arr1 = [1, 2, 3];
$arr2 = ['a' => 4];
$arr3 = [...$arr1, ...$arr2];
// Fatal error: Uncaught Error: Cannot unpack array with string keys in example.php:5

$arr4 = [1, 2, 3];
$arr5 = [4, 5];
$arr6 = [...$arr4, ...$arr5]; // works. [1, 2, 3, 4, 5]
?>

Тип масивів у PHP дуже універсальний. Ось декілька прикладів:

<?php
// This:
$a = array( 'color' => 'red',
            'taste' => 'sweet',
            'shape' => 'round',
            'name'  => 'apple',
            4        // key will be 0
          );

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

// . . .is completely equivalent with this:
$a = array();
$a['color'] = 'red';
$a['taste'] = 'sweet';
$a['shape'] = 'round';
$a['name']  = 'apple';
$a[]        = 4;        // key will be 0

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

// After the above code is executed, $a will be the array
// array('color' => 'red', 'taste' => 'sweet', 'shape' => 'round', 
// 'name' => 'apple', 0 => 4), and $b will be the array 
// array(0 => 'a', 1 => 'b', 2 => 'c'), or simply array('a', 'b', 'c').
?>

Приклад #11 Використання array()

<?php
// Array as (property-)map
$map = array( 'version'    => 4,
              'OS'         => 'Linux',
              'lang'       => 'english',
              'short_tags' => true
            );
            
// strictly numerical keys
$array = array( 7,
                8,
                0,
                156,
                -10
              );
// this is the same as array(0 => 7, 1 => 8, ...)

$switching = array(         10, // key = 0
                    5    =>  6,
                    3    =>  7, 
                    'a'  =>  4,
                            11, // key = 6 (maximum of integer-indices was 5)
                    '8'  =>  2, // key = 8 (integer!)
                    '02' => 77, // key = '02'
                    0    => 12  // the value 10 will be overwritten by 12
                  );
                  
// empty array
$empty = array();         
?>

Приклад #12 Колекція

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

foreach ($colors as $color) {
    echo "Do you like $color?\n";
}

?>

Змінювати значення масиву напряму можна, передавши їх за посиланням.

Приклад #13 Зміна елементу в циклі

<?php
foreach ($colors as &$color) {
    $color = strtoupper($color);
}
unset($color); /* ensure that following writes to
$color will not modify the last array element */

print_r($colors);
?>

У цьому прикладі створюється масив на основі одного елементу.

Приклад #14 Індекс на основі одного показника

<?php
$firstquarter  = array(1 => 'January', 'February', 'March');
print_r($firstquarter);
?>

Приклад #15 Заповнення масиву

<?php
// fill an array with all items from a directory
$handle = opendir('.');
while (false !== ($file = readdir($handle))) {
    $files[] = $file;
}
closedir($handle); 
?>

Масиви впорядковані. Порядок можна змінити за допомогою різних функцій сортування. Для отримання додаткової інформації дивіться розділ Функції роботи з масивами. Функція count() може бути використана для підрахунку кількості елементів у масиві.

Приклад #16 Сортування масиву

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

Оскільки значенням масиву може бути будь-що, він також може бути іншим масивом. Це дозволяє створювати рекурсивні та багатовимірні масиви.

Приклад #17 Рекурсивні та багатовимірні масиви

<?php
$fruits = array ( "fruits"  => array ( "a" => "orange",
                                       "b" => "banana",
                                       "c" => "apple"
                                     ),
                  "numbers" => array ( 1,
                                       2,
                                       3,
                                       4,
                                       5,
                                       6
                                     ),
                  "holes"   => array (      "first",
                                       5 => "second",
                                            "third"
                                     )
                );

// Some examples to address values in the array above 
echo $fruits["holes"][5];    // prints "second"
echo $fruits["fruits"]["a"]; // prints "orange"
unset($fruits["holes"][0]);  // remove "first"

// Create a new multi-dimensional array
$juices["apple"]["green"] = "good"; 
?>

Присвоєння масиву завжди передбачає копіювання значення. Для копіювання масиву за посиланням використовується оператор посилання.

<?php
$arr1 = array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 is changed,
             // $arr1 is still array(2, 3)
             
$arr3 = &$arr1;
$arr3[] = 4; // now $arr1 and $arr3 are the same
?>