PHP 中的數組實際上是一個有序映射。映射是一種把 values 關聯到 keys 的類型。此類型在很多方面做了最佳化,因此可以把它當成真正的數組,或列表(向量),散列表(是映射的一種實現),字典,集合,棧,隊列以及更多可能性。由於數組元素的值也可以是另一個數組,樹形結構和多維陣列也是允許的。
解釋這些結構超出了本手冊的範圍,但對於每種結構至少會提供一個例子。要得到這些結構的更多資訊,建議參考有關此廣闊主題的其它著作。
文法
定義數組 array()
可以用 array() 語言結構來建立一個數組。它接受任意數量用逗號分隔的 鍵(key) => 值(value)對。
array( key => value
, ...
)
// 鍵(key)可是是一個整數 integer 或字串 string
// 值(value)可以是任意類型的值
最後一個數組單元之後的逗號可以省略。通常用於單行數組定義中,例如常用 array(1, 2) 而不是 array(1, 2, )。對多行數組定義通常保留最後一個逗號,這樣要添加一個新單元時更方便。
自 5.4 起可以使用短數組定義文法,用 [] 替代 array()。
Example #1 一個簡單數組
<?php$array = array( "foo" => "bar", "bar" => "foo",); // 自 PHP 5.4 起$array = [ "foo" => "bar", "bar" => "foo",];?>
key 可以是 integer 或者 string。value 可以是任意類型。
此外 key 會有如下的強制轉換:
包含有合法整型值的字串會被轉換為整型。例如鍵名 "8" 實際會被儲存為 8。但是 "08" 則不會強制轉換,因為其不是一個合法的十進位數值。
浮點數也會被轉換為整型,意味著其小數部分會被捨去。例如鍵名 8.7 實際會被儲存為 8。
布爾值也會被轉換成整型。即鍵名 true 實際會被儲存為 1 而鍵名 false 會被儲存為 0。
Null 會被轉換為空白字串,即鍵名 null 實際會被儲存為 ""。
數組和對象不能被用為鍵名。堅持這麼做會導致警告:Illegal offset type。
如果在數組定義中多個單元都使用了同一個鍵名,則只使用了最後一個,之前的都被覆蓋了。
Example #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 實際並不區分索引數組和關聯陣列。
如果對給出的值沒有指定鍵名,則取當前最大的整數索引值,而新的鍵名將是該值加一。如果指定的鍵名已經有了值,則該值會被覆蓋。
Example #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 作為新的鍵名。
Example #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"}
還可以只對某些單元指定鍵名而對其它的空置:
Example #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] 文法來訪問。
Example #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"
Note:
方括弧和花括弧可以互換使用來訪問數組單元(例如 $array[42] 和 $array{42} 在上例中效果相同)。
自 PHP 5.4 起可以用數組間接引用函數或方法調用的結果。之前只能通過一個臨時變數。
自 PHP 5.5 起可以用數組間接引用一個數組原型。
Example #7 數組間接引用
<?phpfunction getArray() { return array(1, 2, 3);} // on PHP 5.4$secondElement = getArray()[1]; // previously$tmp = getArray();$secondElement = $tmp[1];// orlist(, $secondElement) = getArray();?>
Note:
試圖訪問一個未定義的數組鍵名與訪問任何未定義變數一樣:會導致 E_NOTICE 層級錯誤資訊,其結果為 NULL。
用方括弧的文法建立/修改
可以通過明示地設定其中的值來修改一個已有數組。
這是通過在方括弧內指定鍵名來給數組賦值實現的。也可以省略鍵名,在這種情況下給變數名加上一對空的方括弧([])。
$arr[key] = value;
$arr[] = value;
// key 可以是 integer 或 string
// value 可以是任意類型的值
如果 $arr 還不存在,將會建立一個,這也是另一種建立數組的方法。不過並不鼓勵這樣做,因為如果 $arr 已經包含有值(例如來自請求變數的 string)則此值會保留而 [] 實際上代表著字串訪問運算子。初始設定變數的最好方式是直接給其賦值。。
要修改某個值,通過其鍵名給該單元賦一個新值。要刪除某索引值對,對其調用 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 arrayunset($arr); // This deletes the whole array?>
Note:
如上所述,如果給出方括弧但沒有指定鍵名,則取當前最大整數索引值,新的鍵名將是該值加上 1(但是最小為 0)。如果當前還沒有整數索引,則鍵名將為 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)
實用函數
有很多運算元組的函數,參見數組函數一節。
Note:
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'] 而不是 $foo[bar]。但是為什麼呢?可能在老的指令碼中見過如下文法:
<?php$foo[bar] = 'enemy';echo $foo[bar];// etc?>
這樣是錯的,但可以正常運行。那麼為什麼錯了呢?原因是此代碼中有一個未定義的常量(bar)而不是字串('bar'-注意引號),而 PHP 可能會在以後定義此常量,不幸的是你的代碼中有同樣的名字。它能運行,是因為 PHP 自動將裸字串(沒有引號的字串且不對應於任何已知符號)轉換成一個其值為該裸字串的正常字串。例如,如果沒有常量定義為 bar,PHP 將把它替代為 'bar' 並使用之。
Note: 這並不意味著總是給鍵名加上引號。用不著給鍵名為常量或變數的加上引號,否則會使 PHP 不能解析它們。
<?phperror_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";}?>
以上常式會輸出:
Checking 0:
Notice: Undefined index: $i in /path/to/script.html on line 9
Bad:
Good: 1
Notice: Undefined index: $i in /path/to/script.html on line 11
Bad:
Good: 1
Checking 1:
Notice: Undefined index: $i in /path/to/script.html on line 9
Bad:
Good: 2
Notice: Undefined index: $i in /path/to/script.html on line 11
Bad:
Good: 2
示範此行為的更多例子:
<?php// Show all errorserror_reporting(E_ALL); $arr = array('fruit' => 'apple', 'veggie' => 'carrot'); // Correctprint $arr['fruit']; // appleprint $arr['veggie']; // carrot // Incorrect. This works but also throws a PHP error of level E_NOTICE because// of an undefined constant named fruit//// Notice: Use of undefined constant fruit - assumed 'fruit' in...print $arr[fruit]; // apple // This defines a constant to demonstrate what's going on. The value 'veggie'// is assigned to a constant named fruit.define('fruit', 'veggie'); // Notice the difference nowprint $arr['fruit']; // appleprint $arr[fruit]; // carrot // The following is okay, as it's inside a string. Constants are not looked for// within strings, so no E_NOTICE occurs hereprint "Hello $arr[fruit]"; // Hello apple // With one exception: braces surrounding arrays within strings allows constants// to be interpretedprint "Hello {$arr[fruit]}"; // Hello carrotprint "Hello {$arr['fruit']}"; // Hello apple // This will not work, and will result in a parse error, such as:// Parse error: parse error, expecting T_STRING' or T_VARIABLE' or T_NUM_STRING'// This of course applies to using superglobals in strings as wellprint "Hello $arr['fruit']";print "Hello $_GET['foo']"; // Concatenation is another optionprint "Hello " . $arr['fruit']; // Hello apple?>
當開啟 error_reporting 來顯示 E_NOTICE 層級的錯誤(將其設為 E_ALL)時將看到這些錯誤。預設情況下 error_reporting 被關閉不顯示這些。
和在文法一節中規定的一樣,在方括弧(“[”和“]”)之間必須有一個運算式。這意味著可以這樣寫:
<?phpecho $arr[somefunc($bar)];?>
這是一個用函數傳回值作為數組索引的例子。PHP 也可以用已知常量,可能之前已經見過:
<?php$error_descriptions[E_ERROR] = "A fatal error has occured";$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 occured";$error_descriptions[2] = "PHP issued a warning";$error_descriptions[8] = "This is just an informal notice";?>
因為 E_ERROR 等於 1,等等。
那麼為什麼這樣做不好?
也許有一天,PHP 開發小組可能會想新增一個常量或者關鍵字,或者使用者可能希望以後在自己的程式中引入新的常量,那就有麻煩了。例如已經不能這樣用 empty 和 default 這兩個詞了,因為他們是保留字。
Note: 重申一次,在雙引號字串中,不給索引加上引號是合法的因此 "$foo[bar]" 是合法的(“合法”的原文為 valid。在實際測試中,這麼做確實可以訪問數組的該元素,但是會報一個常量未定義的 notice。無論如何,強烈建議不要使用 $foo[bar]這樣的寫法,而要使用 $foo['bar'] 來訪問數組中元素。--haohappy 注)。至於為什麼參見以上的例子和字串中的變數解析中的解釋。
轉換為數組
對於任意 integer,float,string,boolean 和 resource 類型,如果將一個值轉換為數組,將得到一個僅有一個元素的數組,其下標為 0,該元素即為此標量的值。換句話說,(array)$scalarValue 與 array($scalarValue) 完全一樣。
如果一個 object 類型轉換為 array,則結果為一個數組,其單元為該對象的屬性。鍵名將為成員變數名,不過有幾點例外:整數屬性不可訪問;私人變數前會加上類名作首碼;保護變數前會加上一個 '*' 做首碼。這些首碼的前後都各有一個 NULL 字元。這會導致一些不可預知的行為:
<?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'。
將 NULL 轉換為 array 會得到一個空的數組。
比較
可以用 array_diff() 和數組運算子來比較數組。
樣本
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').?>
Example #8 使用 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();?>
Example #9 集合
<?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 #10 在迴圈中改變單元
<?php// PHP 5foreach ($colors as &$color) { $color = strtoupper($color);}unset($color); /* ensure that following writes to$color will not modify the last array element */ // Workaround for older versionsforeach ($colors as $key => $color) { $colors[$key] = strtoupper($color);} print_r($colors);?>
以上常式會輸出:
Array([0] => RED[1] => BLUE[2] => GREEN[3] => YELLOW)
本例產生一個下標從 1 開始的數組。
Example #11 下標從 1 開始的數組
<?php$firstquarter = array(1 => 'January', 'February', 'March');print_r($firstquarter);?>
以上常式會輸出:
Array
(
[1] => 'January'
[2] => 'February'
[3] => 'March'
)
Example #12 填充數組
<?php// fill an array with all items from a directory$handle = opendir('.');while (false !== ($file = readdir($handle))) { $files[] = $file;}closedir($handle);?>
數組是有序的。也可以使用不同的排序函數來改變順序。更多資訊參見數組函數。可以用 count() 函數來數出數組中元素的個數。
Example #13 數組排序
<?phpsort($files);print_r($files);?>
因為數組中的值可以為任意值,也可是另一個數組。這樣可以產生遞迴或多維陣列。
Example #14 遞迴和多維陣列
<?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 aboveecho $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";?>
數組(Array) 的賦值總是會涉及到值的拷貝。使用引用運算子通過引用來拷貝數組。
<?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?>