PHPのお勉強!

PHP TOP

配列

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 だからです。

例6 複雑な型のキャストと上書きの例

以下の例は、型のキャストされた時と、要素が上書きされる時の全ての場合を示しています。

<?php
$array
= array(
1 => 'a',
'1' => 'b', // 値 "a" は "b" で上書きされます。
1.5 => 'c', // 値 "b" は "c" で上書きされます。
-1 => 'd',
'01' => 'e', // この値は数値文字列ではないので、キー1を上書きしません
'1.5' => 'f', // この値は数値文字列ではないので、キー1を上書きしません
true => 'g', // 値 "c" は "g" で上書きされます。
false => 'h',
'' => 'i',
null => 'j', // 値 "i" は "j" で上書きされます。
'k', // 値 "k" にはキー2が割り当てられます。なぜなら、これより前のキーの最大値は1だからです。
2 => 'l', // 値 "k" は "l" で上書きされます。
);

var_dump($array);
?>

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

array(7) {
  [1]=>
  string(1) "g"
  [-1]=>
  string(1) "d"
  ["01"]=>
  string(1) "e"
  ["1.5"]=>
  string(1) "f"
  [0]=>
  string(1) "h"
  [""]=>
  string(1) "j"
  [2]=>
  string(1) "l"
}

角括弧構文による配列要素へのアクセス

配列の要素へのアクセスには array[key] 構文を使います。

例7 配列の要素へのアクセス

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

注意:

PHP 8.0.0 より前のバージョンでは、 配列の要素にアクセスするときに、 角括弧と波括弧がどちらも同じ意味で使えていました。 (つまり、この例で $array[42]$array{42} は同じものを表しているということです)。 波括弧で配列にアクセスする文法は、 PHP 7.4.0 以降は非推奨になり、 PHP 8.0.0 以降はサポートされなくなっています。

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

<?php
function getArray() {
return array(
1, 2, 3);
}

$secondElement = getArray()[1];
?>

注意:

配列に定義されていないキーへアクセスしたときの挙動は、 未定義の変数にアクセスしたときと同じです。 つまり、E_WARNING レベルの警告 (PHP 8.0.0 より前のバージョンでは E_NOTICE) が発生し、結果が null になります。

注意:

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

角括弧構文で作成/修正

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

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

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

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

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

注意: PHP 8.1.0 以降では、 false に設定している値から新しく配列を作成することは推奨されません。 null や未定義の値から配列を新しく作成することはまだ許可されています。

ある値を変更するには、 新しい値に値を代入します。特定のキー/値の組を削除したい場合には、 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
)

配列の分解

配列は、言語構造 [] (PHP 7.1.0 以降) または、list() を使って分解することができます。 これらの言語構造は、 配列を個別の値に分解する用途に使えます。

<?php
$source_array
= ['foo', 'bar', 'baz'];

[
$foo, $bar, $baz] = $source_array;

echo
$foo; // "foo" を出力します。
echo $bar; // "bar" を出力します。
echo $baz; // "baz" を出力します。
?>

これは、多次元配列を foreach で反復処理しながら分解する用途に使えます。

<?php
$source_array
= [
[
1, 'John'],
[
2, 'Jane'],
];

foreach (
$source_array as [$id, $name]) {
// $id と $name を使うロジックをここに書きます
}
?>

変数が与えられない配列の要素は無視されます。 配列の分解は、常にインデックス 0 から始まります。

<?php
$source_array
= ['foo', 'bar', 'baz'];

// インデックス2の要素を、変数 $baz に代入します
[, , $baz] = $source_array;

echo
$baz; // "baz" を出力します。
?>

PHP 7.1.0 以降では、 連想配列も分解できるようになりました。 数値をキーとした配列の右側の要素を、 インデックスを明示的に指定することで簡単に選択できるようになっています。

<?php
$source_array
= ['foo' => 1, 'bar' => 2, 'baz' => 3];

// インデックス 'baz' の要素を、変数 $three に代入します。
['baz' => $three] = $source_array;

echo
$three; // 3 を出力します。

$source_array = ['foo', 'bar', 'baz'];

// インデックス 2 の要素を、変数 $baz に代入します。
[2 => $baz] = $source_array;

echo
$baz; // "baz" を出力します。
?>

配列の分解を使うと、2つの変数を簡単に入れ替えることができます。

<?php
$a
= 1;
$b = 2;

[
$b, $a] = [$a, $b];

echo
$a; // 2 を出力します。
echo $b; // 1 を出力します。
?>

注意:

分解時に値を代入する際には、... 演算子はサポートされていません。

注意:

定義されていない配列のキーにアクセスしようとすると、 未定義の変数にアクセスする場合と同じ扱いになります。 つまり、E_WARNING レベルの警告 (PHP 8.0.0 より前のバージョンでは E_NOTICE) が発生し、結果が null になります。

有用な関数

配列で使用する便利な関数がたくさんあります。 配列関数 の節を参照ください。

注意:

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' という文字列でそれを置換して使用します。

警告

生の文字列を未定義の定数として扱う振る舞いは、 E_NOTICE レベルの警告が発生します。 この振る舞いは PHP 7.2.0 以降は推奨されなくなり、 E_WARNING レベルの警告が発生します。 PHP 8.0.0 以降は、この振る舞いは削除され、 Error 例外がスローされるようになっています。

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