| PHP Ръководство | ||
|---|---|---|
| Предишна страница | Глава 11. Типове | Следваща страница |
Масивът в PHP всъщност представлява подредена асоциация (ordered map). Асоциацията е тип, който асоциира стойности към ключове. Този тип е оптимизиран по няколко направления, така че можете да го използвате като реален масив, като списък (вектор), хеш-таблица (което е реализация на асоциация), речник, колекция, стек, опашка и др. Тъй като за стойност може да имате друг масив, много лесно можете да симулирате и дървета.
Описанието на тези структури от данни е извън обхвата на това ръководство, но ще намерите поне един пример за всяка от тях. За повече информация по тази обширна тема ви препоръчваме да се насочите към външна литература.
Масив може да бъде създаден посредством езиковата конструкция array(). Тя приема определено количество двойки ключ => стойност , разделени със запетаи.
array( [ключ =>] стойност
, ...
)
// ключът може да бъде цяло число или низ
// стойността може да бъде всякаква |
Ключът може да бъде или цяло число или низ. Ако ключът е представен като обикновено цяло число, той ще бъде интерпретиран като такова (т.е. "8" ще се интерпретира като 8, докато "08" - като "08"). Плаващите числа в ключовете се съкращават до цели. В PHP не съществуват различни типове за индексирани и асоциативни масиви; има само един тип масив, който може да съдържа едновременно целочислени и низови индекси.
Стойността може да бъде от всякакъв тип.
<?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. Ако укажете ключ, който вече има присвоена стойност, то тази стойност ще бъде презаписана.
<?php // Този масив е същият като ... array(5 => 43, 32, 56, "b" => 12); // ...този. array(5 => 43, 6 => 32, 7 => 56, "b" => 12); ?> |
| Внимание |
|
От PHP 4.3.0 насам поведението за генериране на индекси се промени. Сега ако добавяте към масив, в който текущия максимален ключ е отрицателен, следващият създаден ключ ще бъде нула (0). А преди, новият индекс щеше да бъде установен в най-големия съществуващ ключ + 1, както е случая с положителните индекси. |
Използването на TRUE като ключ ще се изчисли като целочислено 1 за ключа. Употребата на FALSE като ключ ще се изчисли като целочислено 0 за ключа. Използването на NULL като ключ ще се изчисли като празнен низ. Употребата на празен низ като ключ ще създаде (или презапише) ключ с празен низ и съответната му стойност; това не е същото като използването на празни квадратни скоби.
Не можете да използвате масиви или обекти като ключове. Ако се опитате да го направите ще предизвикате предупреждение: Illegal offset type (невалиден тип отместване).
Можете също да променяте съществуващ масив чрез изрично установяване на стойностите в него.
Това се осъществява чрез присвояване на стойностите в масива, като ключовете се указват в квадратни скоби. Можете също да пропуснете ключа като добавите празна двойка квадратни скоби ("[]") към името на променливата.
$arr[key] = value; $arr[] = value; // key може да бъде цяло число или низ // value може да бъде каква да е стойност |
$arr все още не съществува, той ще бъде създаден.
Така че това също е и алтернативен начин за указване на масив.
За да промените дадена стойност, просто присвоете нова стойност на елемента,
указан чрез ключа му. Ако искате да премахнете някоя двойка ключ/стойност,
трябва да я унищожите посредством unset().
<?php
$arr = array(5 => 1, 12 => 2);
$arr[] = 56; // Това е същото като $arr[13] = 56;
// в този момент на скрипта
$arr["x"] = 42; // Това добавя нов елемент към
// масива с ключ "x"
unset($arr[5]); // Това премахва елемента от масива
unset($arr); // Това изтрива целия масив
?> |
Забележка: Както беше споменато по-горе, ако предоставите квадратните скоби без указан ключ, тогава ще бъде взет максималния съществуващ целочислен индекс и новият ключ ще бъде тази стойност + 1 . Ако все още няма целочислени индекси, ключът ще бъде 0 (нула). Ако укажете ключ, който вече има присвоена стойност, то тази стойност ще бъде презаписана.
Внимание От PHP 4.3.0 насам поведението за генериране на индекси, описано по-горе, се промени. Сега ако добавяте към масив, в който текущият максимален ключ е отрицателен, следващият създаден ключ ще бъде нула (0). А преди, новият индекс щеше да бъде установен в най-големия съществуващ ключ + 1, както е случая с положителните индекси.
Забележете, че максималната целочислена стойност, използвана за целта, не е задължително да същестува в масива в момента. Тя просто трябва да е съществувала някога в масива от последния път, когато масивът е бил повторно индексиран. Следният пример пояснява:
<?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().
Контролната структура foreach е създадена специално за масиви. Тя предоставя лесен начин за обхождане на масив.
Винаги трябва да заграждате низовите индекси на масиви с апострофи. Например използвайте $foo['bar'], а не $foo[bar]. Но защо все пак $foo[bar] е неправилно? Може би сте виждали следния синтаксис в по-стари скриптове:
Това е погрешно, но работи. Защо тогава все пак е погрешно? Причината е, че този код използва недефинирана константа (bar), а не низ ('bar' - забележете апострофите) и в бъдеще е възможно PHP да дефинира константи, които за нещастие на кода ви, да имат същото име. Това работи, защото PHP автоматично преобразува голия низ (не-апострофиран низ, който не отговаря на нито един известен символ) в низ, съдържащ голия низ. Например ако няма дефинирана константа bar, PHP ще сложи на нейно място низа '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
// Let's show all errors
error_reporting(E_ALL);
$arr = array('fruit' => 'apple', 'veggie' => 'carrot');
// Правилно
print $arr['fruit']; // apple
print $arr['veggie']; // carrot
// Неправилно. Това работи, но също така хвърля грешка в PHP от ниво
// E_NOTICE, заради недефинирана константа fruit
//
// Notice: Use of undefined constant fruit - assumed 'fruit' in...
print $arr[fruit]; // apple
// Нека дефинираме константа, за да демонстрираме какво става. Ще
// присвоим стойност 'veggie' на константа fruit.
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 също разбира и от константи, както може би видяхте в случая с тези от вида E_*.<?php $error_descriptions[E_ERROR] = "Настъпи фатална грешка"; $error_descriptions[E_WARNING] = "PHP изведе предупреждение"; $error_descriptions[E_NOTICE] = "Това е просто информиращо съобщение"; ?> |
<?php $error_descriptions[1] = "Настъпи фатална грешка"; $error_descriptions[2] = "PHP изведе предупреждение"; $error_descriptions[8] = "Това е просто информиращо съобщение"; ?> |
Както вече обяснихме по-горе, $foo[bar] работи, но е погрешно. Работи, понеже се очаква bar, заради синтаксиса си, да бъде константен израз. В този случай, обаче, не съществува константа с името bar. Тогава PHP приема, че сте имали предвид литерала bar, като низа "bar", но че сте забравили да напишете кавичките.
В даден момент от бъдещето е възможно екипът на PHP да реши да добави нова константа или ключова дума, или пък вие да решите да добавите константа в собственото си приложение и в този случай се оказвате в беда. Например, вече не можете да използвате думите empty и default по този начин, защото те са специални запазени ключови думи.
Забележка: Да повторим, в рамките на низ, ограден от кавички, е валидно да не заграждате индексите на масивите с апострофи - така "$foo[bar]" е валидно. Вижте горните примери за причините, както и разделът за синтактичен разбор на променливи в низ.
За всеки от типовете: цяло число, плаващо, низ, булев или ресурс, ако преобразувате стойност в масив ще получите масив с единствен елемент (с индекс 0), който е скаларната стойност, която сте подали.
Ако преобразувате обект в масив ще получите свойствата (член-променливите) на обекта като елементи на масива. Ключовете са имената на член-променливите, с някои изключния: частните (private) променливи имат името на класа пред името на променливата; защитените (protected) променливи имат "*" пред името на променливата. Тези допълнителни стойности имат null байт от двете страни. Това би могло да доведе до неочаквани резултати.
<?php
class A {
private $A; // Това ще стане '\0A\0A'
}
class B extends A {
private $A; // Това ще стане '\0B\0A'
public $AA; // Това ще стане 'AA'
}
var_dump((array) new B());
?> |
Ако преобразувате стойността NULL в масив ще получите празен масив.
Можете да сравнявате масиви посредством array_diff() или чрез някой от Операторите за масиви.
Типът масив в PHP е много гъвкав, така че ето няколко примера, които да демонстрират пълната мощ на масивите.
<?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')
?> |
Прякото променяне на стойности в масив е възможно след PHP 5 чрез подаването им по референция. Предишните версии се нуждаят от заобиколно решение:
Пример 11-8. Колекция
Примерът по-горе ще изведе:
|
Този пример създава масив, започвайки с ключ едно.
Масивите са подредени. Можете също да променяте реда с помощта на някоя подреждаща функции. Вижте раздел функции за масиви за повече информация. Можете да получите броя на елементите в масив с функцията count().
Тъй като стойността на масив може да бъде всякаква, то съответно тя може да бъде и друг масив. По този начин можете да правите рекурсивни и много-измерни масиви.
Пример 11-12. Рекурсивни и много-измерни масиви
|
Трябва да сте наясно, че присвояването в масиви винаги става с копиране по стойност. Това също означава, че вътрешният масивен указател, използван от current() и подобните й функции, се изчиства. За да копирате масив по референция, трябва да използвате референтния оператор.