Типове
PHP Manual

Масиви

Масивът в PHP всъщност представлява подредена асоциация (ordered map). Асоциацията е тип, който асоциира стойности към ключове. Този тип е оптимизиран по няколко направления, така че можете да го използвате като реален масив, като списък (вектор), хеш-таблица (което е реализация на асоциация), речник, колекция, стек, опашка и др. Тъй като за стойност може да имате друг масив, много лесно можете да симулирате и дървета.

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

Синтаксис

Указване посредством array()

Масив може да бъде създаден посредством езиковата конструкция array(). Тя приема определено количество двойки ключ => стойност , разделени със запетаи.

array(  ключ =>  стойност
     , ...
     )
// ключът може да бъде цяло число или низ
// стойността може да бъде всякаква
    

<?php
$arr 
= array("foo" => "bar"12 => true);

echo 
$arr["foo"]; // bar
echo $arr[12];    // 1
?>

Ключът може да бъде или цяло число, или низ. Ако ключът е представен като обикновено цяло число, той ще бъде интерпретиран като такова (т.е. "8" ще се интерпретира като 8, докато "08" - като "08"). Плаващите числа в ключовете се съкращават до цели. В PHP не съществуват различни типове за индексирани и асоциативни масиви; има само един тип масив, който може да съдържа едновременно целочислени и низови индекси.

Стойността може да бъде от всякакъв тип.

<?php
$arr 
= array("somearray" => array(=> 513 => 9"a" => 42));

echo 
$arr["somearray"][6];    // 5
echo $arr["somearray"][13];   // 9
echo $arr["somearray"]["a"];  // 42
?>

Ако не укажете изрично ключ за дадена стойност, то ще се вземе най-голямата стойност от целочислените индекси и новият ключ ще бъде тази стойност + 1. Ако укажете ключ, който вече има присвоена стойност, то тази стойност ще бъде презаписана.

<?php
// Този масив е същият като ...
array(=> 433256"b" => 12);

// ...този.
array(=> 43=> 32=> 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(=> 112 => 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(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(=> 'one'=> 'two'=> 'three');
unset(
$a[2]);
/* ще доведе до масив, който би бил дефиниран като
   $a = array(1 => 'one', 3 => 'three');
   а НЕ като
   $a = array(1 => 'one', 2 =>'three');
*/

$b array_values($a);
// Сега $b е array(0 => 'one', 1 =>'three')
?>


Контролната структура foreach е създадена специално за масиви. Тя предоставя лесен начин за обхождане на масив.

Правилна и неправилна употреба на масиви

Защо $foo[bar] е погрешно?

Винаги трябва да заграждате низовите индекси на масиви с апострофи. Например използвайте $foo['bar'], а не $foo[bar]. Но защо все пак $foo[bar] е неправилно? Може би сте виждали следния синтаксис в по-стари скриптове:

<?php
$foo
[bar] = 'враг';
echo 
$foo[bar];
// etc
?>

Това е погрешно, но работи. Защо тогава все пак е погрешно? Причината е, че този код използва недефинирана константа (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(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
// 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
echo $arr[somefunc($bar)];
?>

Това е пример за използване на стойност, върната от функция, като индекс на масив. PHP също разбира и от константи, както може би сте забелязали в случая с тези от вида E_*.

<?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, и т.н.

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

Защо е лошо тогава?

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

Забележка: Да повторим, в рамките на низ, ограден от кавички, е валидно да не заграждате индексите на масивите с апострофи - така "$foo[bar]" е валидно. Вижте горните примери за причините, както и разделът за синтактичен разбор на променливи в низ.

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

За всеки от типовете: integer (цяло число), float (плаващ), string (низ), boolean (булев) или resource (ресурс), ако преобразувате стойност в масив ще получите масив с единствен елемент (с индекс 0), който е скаларната стойност, която сте подали.

Ако преобразувате обект в масив ще получите свойствата (член-променливите) на обекта като елементи на масива. Ключовете са имената на член-променливите, с някои изключния: частните (private) променливи ще имат добавено името на класа пред името на променливата; защитените (protected) променливи ще имат добавено "*" пред името на променливата. Тези допълнителни стойности имат null байт от двете страни. Това би могло да доведе до неочаквани резултати.

<?php

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

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

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

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

Ако преобразувате стойността 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')
?>

Example #1 Употреба на 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();         
?>

Example #2 Колекция

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

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

?>

Примерът по-горе ще изведе:

Do you like red?
Do you like blue?
Do you like green?
Do you like yellow?

Прякото променяне на стойности в масив е възможно след PHP 5 чрез подаването им по референция. Предишните версии се нуждаят от заобиколно решение:

Example #3 Колекция

<?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
)

Този пример създава масив, започвайки с ключ едно.

Example #4 Едно-базиран индекс

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

Примерът по-горе ще изведе:

Array 
(
    [1] => 'January'
    [2] => 'February'
    [3] => 'March'
)

Example #5 Попълване на масив

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

Масивите са подредени. Можете също да променяте реда с помощта на някоя подреждаща функции. Вижте раздел функции за масиви за повече информация. Можете да получите броя на елементите в масив с функцията count().

Example #6 Подреждане на масив

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

Тъй като стойността на масив може да бъде всякаква, то съответно тя може да бъде и друг масив. По този начин можете да правите рекурсивни и многомерни масиви.

Example #7 Рекурсивни и многомерни масиви

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

// някои примери за достъп до масива по-горе
echo $fruits["holes"][5];    // отпечатва "second"
echo $fruits["fruits"]["a"]; // отпечатва "orange"
unset($fruits["holes"][0]);  // премахва "first"

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

Трябва да сте наясно, че присвояването в масиви винаги става с копиране по стойност. Това също означава, че вътрешният масивен указател, използван от current() и подобните й функции, се изчиства. За да копирате масив по референция, трябва да използвате референтния оператор.

<?php
$arr1 
= array(23);
$arr2 $arr1;
$arr2[] = 4// $arr2 е променен,
             // $arr1 е все още array(2, 3)
             
$arr3 = &$arr1;
$arr3[] = 4// сега $arr1 и $arr3 са едно и също
?>


Типове
PHP Manual