配列

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" として解釈されます)。 key に浮動小数点数値を指定すると、 その値は integer に切り詰められます。 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);
?>

警告

PHP 4.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 になります。 既に値が割り当てられているキーを指定した場合には、 値は上書きされます。

警告

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

// アイテムを追加します(新しい添え字は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(0 => 'one', 1 =>'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);
// 単純な配列
$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]" は有効です。 この理由の詳細については、上記の例や 文字列中での変数のパースを参照してください。

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

配列への変換

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

objectを配列にする場合には、配列の要素として オブジェクトの属性 (メンバ変数) を持つ配列を得ることになります。 添字はメンバ変数名となりますが、いくつか注意すべき例外があります。 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());
?>

上の例では 'AA' というキーがふたつあるように見えますが、 そのうちひとつは、実際は '\0A\0A' ということになります。

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

比較

array_diff()配列演算子 を用いると、配列を比較することができます。

PHP の配列型は、いろいろな使い方ができます。配列の強力な機能を示すため、 ここでいくつかの例を紹介します。

<?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') となります
?>

例 11-6. 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();

例 11-7. コレクション

<?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 以降では、配列を参照渡しすることでその値を直接変更できるようになりました。 それ以前のバージョンでは、以下のような回避策が必要です。

例 11-8. コレクション

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

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

例 11-9. 1 から始まる添字

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

上の例の出力は以下となります。

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

例 11-10. 配列に代入する

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

配列には順番が付けられます。異なったソート関数を用いて順番を変更することも可能です。 より詳細な情報については、配列関数 を参照ください。 count() 関数を使用することで、 配列の要素数を数えることが可能です。

例 11-11. 配列のソート

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

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

例 11-12. 再帰および多次元配列

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

// 上の配列の内容を取得するための例
echo $fruits["holes"][5];    // "second" を表示します
echo $fruits["fruits"]["a"]; // "orange" を表示します
unset($fruits["holes"][0]);  // "first"  を削除します

// 新しい多次元配列を作成します
$juices["apple"]["green"] = "good";
?>

配列の割り当てにおいては、常に値がコピーされることに注意してください。 これは、current() および類似の関数が使用する 内部配列ポインタの値がリセットされるということを意味します。 配列をリファレンスでコピーする場合には、 リファレンス演算子を使う必要があります。

<?php
$arr1
= array(2, 3);
$arr2 = $arr1;
$arr2[] = 4; // $arr2 が変更されます。
             // $arr1 は array(2,3) のままです。

$arr3 = &$arr1;
$arr3[] = 4; // $arr1 と $arr3 は同じ内容になります。
?>