Php/docs/language.types.array

提供:Dev Guides
< Php
移動先:案内検索

配列

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

これらのデータ構造に関する説明は本マニュアルの範囲を超えるので省略しますが、 各々について、少なくとも一つは例を示します。 この分野は広範囲にまたがり、さまざまな文献が存在します。 より詳細な情報については、それらの文献を参照ください。

構文

array() で指定

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

array(
    key  => value,
    key2 => value2,
    key3 => value3,
    ...
)

最後の要素のあとのカンマは、書いても書かなくてもかまいません。 配列を一行で定義する場合は、ふつうは最後のカンマを省略します。つまり、 array(1, 2) のほうが array(1, 2, ) よりおすすめだということです。 しかし複数行で定義する場合は、最後のカンマをつけることが一般的です。 そうしておけば、配列の最後に要素を追加するのが容易になるからです。

注意:

array()[] で置き換えることが出来る、配列の短縮構文も使えます。

例1 シンプルな配列定義

<?php$array = array(    "foo" => "bar",    "bar" => "foo",);// 配列の短縮構文$array = [    "foo" => "bar",    "bar" => "foo",];?>

key は、整数 または 文字列です。 value には任意の型を指定できます。

さらに、次のような key のキャストが発生します。

  • 10 進数の int として妥当な形式の String は、 数値の前に + 記号がついていない限り、 int 型にキャストされます。 つまり、キーに "8" を指定すると、実際には 8 として格納されるということです。一方 "08" はキャストされません。これは十進数として妥当な形式ではないからです。
  • floats もまた int にキャストされます。つまり、 小数部分は切り捨てられるということです。たとえばキーに 8.7 を指定すると、実際には 8 として格納されます。
  • boolint にキャストされます。つまり、 キーに true を指定すると実際には 1 に格納され、 同様にキーを false とすると実際には 0 となります。
  • Null は空文字列にキャストされます。つまり、キーに null を指定すると、実際には "" として格納されます。
  • arrayobject は、キーとして使えません。 キーとして使おうとすると Illegal offset type という警告が発生します。

配列の宣言時に同じキーで複数の要素を指定すると、 最後に指定したものがそれまでの値を上書きします。

例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 においては添字配列と連想配列の間に違いはなく、配列型は 1 つだけで、 同じ配列で整数のインデックスと文字列のインデックスを同時に使えます。

例3 整数と文字列のキーの混在例

<?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 はこれまでに使われた整数のキーの中で最大のものに 1 を加えた値を使います。

例4 数値添字配列でキーを省略する例

<?php$array = array("foo", "bar", "hello", "world");var_dump($array);?>

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


array(4) {
  [0]=>
  string(3) "foo"
  [1]=>
  string(3) "bar"
  [2]=>
  string(5) "hello"
  [3]=>
  string(5) "world"
}

一部の要素にだけキーを指定することもできます。

例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] 構文を使います。

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

注意:

角括弧と波括弧は、配列の要素にアクセスするときにはどちらも同じ意味で使えます (つまり、この例で $array[42]$array{42} は同じものを表しているということです)。

例7 配列のデリファレンス

<?phpfunction getArray() {    return array(1, 2, 3);}$secondElement = getArray()[1];// または、このように書くことができますlist(, $secondElement) = getArray();?>

注意:

配列に定義されていないキーへアクセスしたときの挙動は、 未定義の変数にアクセスしたときと同じです。 E_NOTICE メッセージが発行され、 返される結果は null となります。

注意:

配列で文字列以外のスカラー値をデリファレンスした場合は、 返される結果は null となります。 PHP 7.4.0 より前のバージョンでは、何もエラーは発生しませんでした。 PHP 7.4.0 以降では、E_NOTICE が発生します。 PHP 8.0.0 以降では、E_WARNING が発生します。

角括弧構文で作成/修正

明示的に値を設定することにより、既存の配列を修正することも可能です。

これは、角括弧の中にキーを指定し、配列に値を代入することにより行います。 キーを省略することも可能です。この場合、空の角括弧 ("[]") の変数名として追加してください。

$arr[キー] = 値;
$arr[] = 値;
// キー は 文字列 または
// 整数のどちらかです。
// 値 の型は、何でもかまいません。
   

$arr がまだ存在しない場合は、新しく作成します。 つまり、これは配列を作成する方法のひとつでもあります。 とはいえ、この方法を使うことはおすすめしません。なぜなら、既に $arr に何らかの値 (リクエスト変数からの文字列など) が入っている場合にはその値がそのまま残り、 [] が実際には 文字列アクセス演算子 を表してしまうからです。 変数を初期化するときには、直接代入するほうがよいでしょう。

注意:

PHP 7.1.0 以降では、文字列に空のインデックス演算子を適用すると fatal エラーが発生するようになりました。 これまでのバージョンではエラーにならず、文字列が配列に変換されていました。

ある値を変更するには、 新しい値に値を代入します。特定のキー/値の組を削除したい場合には、 unset() を使用する必要があります。

<?php$arr = array(5 => 1, 12 => 2);$arr[] = 56;    // このスクリプトのこの位置に記述した場合、                // $arr[13] = 56; と同じです$arr["x"] = 42; // キー"x"の新しい要素を配列に追加します                unset($arr[5]); // 配列から要素を削除しますunset($arr);    // 配列全体を削除します?>

注意:

上記のように、キーを省略して新規要素を追加する場合、 追加される数値添字は、使用されている添字の最大値 +1 (ただし、少なくとも 0 以上) になります。 まだ数値添字が存在しない場合は、添字は 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);// アイテムを追加します(新しい添え字は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) が使用されているためです。 下位互換性の維持のため、未定義の定数は同じ名前の文字列に自動的に変換されます。 そのため、このコードは動作します。 例えば、bar という名前の定義されていない定数があるとすると、 PHP は 'bar' という文字列でそれを置換して使用します。

警告 生の文字列を未定義の定数として扱う振る舞いは、PHP 7.2.0 以降では推奨されなくなり、 E_WARNING レベルの警告が発生するようになりました。 それ以前のバージョンでは、E_NOTICE レベルの警告が発生していました。


注意:

これは、添字を常にクォートするという意味ではありません。 定数変数 を添字として使う際には、クォートしてしまうと PHP はそれを解釈できなくなってしまいます。

<?phperror_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'];  // appleprint $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'];  // appleprint $arr[fruit];    // carrot// 以下は文字列の中であるためOKです。定数は、文字列の中では解釈されな// いため、E_NOTICEエラーはここでは発生しません。print "Hello $arr[fruit]";      // Hello apple// 例外が1つあり、文字列の中で波括弧で配列を括った場合には、// 定数が解釈されますprint "Hello {$arr[fruit]}";    // Hello carrotprint "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 はこれらを表示しない設定になっています。

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

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

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

<?php$error_descriptions[E_ERROR]   = "A fatal error has occurred";$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 occurred";$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]" は有効です。 この理由の詳細については、上記の例や 文字列中での変数のパースを参照してください。

配列への変換

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

objectを配列にする場合には、配列の要素として オブジェクトの属性 (メンバ変数) を持つ配列を得ることになります。 添字はメンバ変数名となりますが、いくつか注意すべき例外があります。 整数のプロパティはアクセス不能になります。 private 変数の場合、変数名の頭にクラス名がつきます。また、 protected 変数の場合は、変数名の頭に '*' がつきます。 このとき、頭に追加される値の前後に null バイトがついてきます。 その結果、予期せぬ振る舞いをすることがあります。

<?phpclass 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// これは、$a = array( 'color' => 'red',            'taste' => 'sweet',            'shape' => 'round',            'name'  => 'apple',            4        // キーは0になります          );$b = array('a', 'b', 'c');// は、完全にこれと同じです。$a = array();$a['color'] = 'red';$a['taste'] = 'sweet';$a['shape'] = 'round';$a['name']  = 'apple';$a[]        = 4;        // キーは0になります$b = array();$b[] = 'a';$b[] = 'b';$b[] = 'c';// 上のコードを実行すると、$a は次のような配列// array('color' => 'red', 'taste' => 'sweet', 'shape' => 'round', // 'name' => 'apple', 0 => 4) となり、$b は// array(0 => 'a', 1 => 'b', 2 => 'c') あるいは単に array('a', 'b', 'c') となります?>

例8 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, // 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();         ?>

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

配列を参照渡しすることでその値を直接変更できます。

例10 ループ内での要素の変更

<?phpforeach ($colors as &$color) {    $color = strtoupper($color);}unset($color); /* これ以降の $color への書き込みが配列の要素を書き換えてしまわないことを保証する */print_r($colors);?>

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


Array
(
    [0] => RED
    [1] => BLUE
    [2] => GREEN
    [3] => YELLOW
)

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

例11 1 から始まる添字

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

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


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

例12 配列に代入する

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

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

例13 配列のソート

<?phpsort($files);print_r($files);?>

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

例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"                                     )                );// 上の配列の内容を取得するための例echo $fruits["holes"][5];    // "second" を表示しますecho $fruits["fruits"]["a"]; // "orange" を表示しますunset($fruits["holes"][0]);  // "first"  を削除します// 新しい多次元配列を作成します$juices["apple"]["green"] = "good"; ?>

配列への代入においては、常に値がコピーされることに注意してください。 配列をリファレンスでコピーする場合には、 リファレンス演算子を使う必要があります。

<?php$arr1 = array(2, 3);$arr2 = $arr1;$arr2[] = 4; // $arr2 が変更されます。             // $arr1 は array(2,3) のままです。             $arr3 = &$arr1;$arr3[] = 4; // $arr1 と $arr3 は同じ内容になります。?>