配列

PHPの配列は、実際には順番付けられたマップです。マップは型の一種で、 キーにマップします。 この型は、いくつかの手法で最適化されます。このため、実際の配列 またはリスト(ベクトル)、(あるマップの実装である)ハッシュテーブル、 ディレクトリ、コレクション、スタック、キュー等として使用することが 可能です。PHPの配列には他のPHP配列を値として保持することができるた め、非常に簡単にツリー構造を表現することが可能です。

これらの構造に関する説明は、本マニュアルの範囲外ですが、これらの構 造に各々に関する例を少なくとも一つ見付けることが可能です。これらの 構造に関するより詳細な情報については、データ構造に関する良書を購入 して下さい。

構文

array()で指定

配列 は、言語に組み込まれた array() で作成することが可能です。この構造は、 特定の数のカンマで区切られた key => valueの組を引数とします。

array( [key =>] value
     , ...
     )
// keyは、文字列または非負の
// 整数です。
// valueに制約はありません.

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

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

key は、整数 または 文字列です。 あるキーが、整数の標準的な表現形式である場合、 そのように解釈されます。(つまり、"8"8として解釈されます。一方、 "08""08"として解釈されま す。) PHPにおいては添字配列と連想配列の間に違いはなく、配列型は1つだ けで、整数または文字列のインデックスを使用することができます。

値には、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となります。整数値は負の数とすることができ、負の添字に ついても同様となります。例えば、最高時の添字が-6 の場合、次のキーは-5となります。 整数添字がまだ存在しない場合、キーは0(ゼロ)となります。 値が既に代入されているキーを指定した場合、元の値は上書きされます。

<?php
// この配列は以下の配列と同じです ...
array(5 => 43, 32, 56, "b" => 12);

// この配列は上の配列と同じです
array(5 => 43, 6 => 32, 7 => 56, "b" => 12);
?>

警告

PHP4.3.0以降、上記のような添字生成動作は変更されました。 現在では、配列に追加する際に、その配列の最大添字が負である 場合は次の添え字はゼロ(0)となります。 以前は、正の添字の場合と同様に新しい添字は最大添字に+1した ものにセットされていました。

キーとして TRUE を使用した場合、 整数型の1がキーとして解釈されます。 キーとして FALSE を使用した場合、 整数型の0がキーとして解釈されます。 キーとしてNULLを使用した場合、空の文字列として評価 されます。キーとして空の文字列を使用すると、空の文字列のキーとその値を 作成(または上書き)します。空の括弧を用いた場合と同じではありません。

配列またはオブジェクトをキーとして使用することはできません。 これを行なうと、warning: 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になります。 既に値が割り当てられているキーを指定した場合には、 値は上書きされます。

警告

PHP4.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);

// アイテムを追加します(新しい添え字は0ではなく
// 5となることに注意)
$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()関数は配列のキーを削除することが出来ます。 ただし、これによってインデックスの再構築が行われるわけでは ないということに気をつけてください。 "通常の整数添字"(0から始まり、1つずつ増加)のみを使用している場合、 array_values()を用いてインデックスを再構築す ることができます。

<?php
$a
= array(1 => 'one', 2 => 'two', 3 => 'three');
unset(
$a[2]);
/* これにより配列は以下の様に定義されます。
   $a = array( 1 => 'one', 3 => 'three');
   以下ではありません:
   $a = array( 1 => 'one', 2 => 'three');
*/

$b = array_values($a);
// bは、array(1 => 'one', 2 =>'three')となります
?>

配列専用の制御構造としてforeachがあります。こ の構造は、配列の要素に簡単に連続的にアクセスする手段を提供します。

配列ですべきこととしてはならないこと

なぜ、$foo[bar] は使用できないのか?

連想配列の添字の前後は常に引用符で括る必要があります。 例えば、$foo[bar]ではなく$foo['bar']を使用して下さい。 しかし、 $foo[bar]はなぜ誤りなのでしょうか? 古いスクリプトで次のような構文を見たことがあるかもしれません。

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

これは間違っていますが、動作します。では、なぜ間違っているのでしょ う? その理由は、このコードには文字列('bar' - 引用符で括られてい る)ではなく未定義の定数(bar)が使用されており、PHPが同じ名前の定 数を不幸にして同じコードの中に定義する可能性があるためです。 下位互換性の維持のために未定義の定数は同じ名前の文字列に自動的に 変換されるため、このコードは動作します。 例えば、barという名前の、定義されていない定数 があるとすると、PHPは'bar'という文字列でそれを 置換して使用します。

注意: これは、添字を常にクォートするという 意味ではありません。定数変数を添字として 使う際には、クォートしてしまうと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";
}
?>

注意: 上記の出力は次のようになります:
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
// エラーを全て表示するよう設定
error_reporting(E_ALL);

$arr = array('fruit' => 'apple', 'veggie' => 'carrot');

// 正しい
print $arr['fruit'];  // apple
print $arr['veggie']; // carrot

// 間違い。これは動作しますが、未定義の定数fruitを使用しているため、
// 同時にE_NOTICEレベルのPHPエラーを発生します
//
// 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

// 以下は文字列の中であるためOKです。定数は、文字列の中では解釈されな
// いため、E_NOTICEエラーはここでは発生しません。
print "Hello $arr[fruit]";      // Hello apple

// 例外が1つあり、文字列の中で波括弧で配列を括った場合には、
// 定数が解釈されます
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_ALLを指定する等により) E_NOTICE レベルのエラー出力を有効にした場合、 上記のエラーが出力されます。 デフォルトでは、 error_reportingはこれらを表示しない設定になっています。

構文の節に記述したように、角括弧の間 ('['および']')には、式がなけれ ばなりません。これは、次のように書くことが可能であることを 意味します。

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

これは、関数の戻り値を配列の添字として使用する例です。PHPは定数に ついても認識し、以下のようなE_*の使用例を見た ことがあるかもしれません。

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

最初の例のbarと全く同様に E_ERROR も有効な添字であることに注意して下さ い。しかし、実際には最後の例は次のように書くことと同じです。

<?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_ERROR1と等し いこと等によります。

では、なぜ $foo[bar] は動作することが可能なの でしょう? それは、bar が定数式であることを 期待される構文で使用されているためです。しかし、この場合、 bar という名前の定数は存在しません。PHPは、 この場合、あなたが文字列"bar"のようにリテラル bar を指定したが引用符を忘れたと仮定します。

では、なぜ間違っているのでしょう?

将来的に、PHPは他の定数またはキーワードを追加したいと思うかもし れず、問題となる可能性があります。例えば、現在でも、 単語 empty および defaultを使用することはできません。 これは、これらが、特別な 予約済みのキーワードである ためです。

注意: 二重引用符で括られた文字列の中では、 引用符で配列の添字を括らないことができ、このため、 "$foo[bar]"は有効です。 この理由の詳細については、上記の例や 文字列中での変数 のパースを参照して下さい。

注意: 2重引用符で括られたstringの中で他の構文が有効です。 より詳細については、文字列の中の変数 を参照下さい。

配列への変換

integer, float, string, boolean, resourceのいずれの型においても、 arrayに変換する場合、最初のスカラー値が割り当てら れている一つの要素(添字は0)を持つ配列を得ることになります。

objectを配列にする場合には、配列の要素として オブジェクトの属性(メンバー変数)を持つ配列を得ることになります。 添字はメンバー変数名となります。

NULL を配列に変換すると、空の配列を得ます。

PHPの配列型は非常に解りにくいため、ここで、配列の強力な機能を示す いくつかの例を紹介します。

// this
$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') となります

例 6-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 // key = 0
                  , 5    =>  6
                  , 3    =>  7
                  , 'a'  =>  4
                  ,         11 // key = 6 (最大の添字は5です)
                  , '8'  =>  2 // key = 8 (整数!)
                  , '02' => 77 // key = '02'
                  , 0    => 12 // 値10は12で上書きされます
                  );
                 
// empty array
$empty = array();

例 6-5. コレクション

<?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?
*/
?>

配列の値をこのようなループで直接変更することはできないことに注意 して下さい。 これを解決するには、次のようにします。

例 6-6. コレクション

<?php
foreach ( $colors as $key => $color ) {
    
// 動作しない:
    //$color = strtoupper($color);
    
    // 動作する:
    
$colors[$key] = strtoupper($color);
}
print_r($colors);

/* 出力:
Array
(
    [0] => RED
    [1] => BLUE
    [2] => GREEN
    [3] => YELLOW
)
*/
?>

この例は、1から始まる配列を作成します。

例 6-7. 1から始まる添字

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

/* 出力:
Array
(
    [1] => 'January'
    [2] => 'February'
    [3] => 'March'
)
*/
?>

例 6-8. 配列に代入する

<?php
// ディレクトリから全てのアイテムを配列に代入する
$handle = opendir('.');
while (
$file = readdir($handle))
{
    
$files[] = $file;
}
closedir($handle);
?>

配列には順番が付けられます。異なったソート関数を用いて順番を変更 することも可能です。より詳細な情報については、配列関数 を参照下さい。 You can count the number of items in an array using the count() function.

例 6-9. 配列のソート

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

配列の値は何でも良いため、その値を他の配列とすることも可能です。 これにより、再帰的な配列や多次元の配列を作成することが可能です。

例 6-10. 再帰および多次元配列

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

// 多次元配列の生成
$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
?>