配列というのはPHPでは連想配列と全く同じものです。
なので配列内の要素を削除した場合は注意しないとバグやエラーの温床になります。
という訳で配列の要素を削除したときに注意すべきことについて解説
まず配列の要素を削除する方法について紹介
まずPHPで配列の要素を削除するにはどうすればいいのか
ということですがunset関数という便利なものがあるのでそれを使います。
この関数はPHPリファレンスだと次のように説明されていました。
void unset ( mixed $var [, mixed $... ] )unset() は指定した変数を破棄します。
関数 unset() の内部動作は、 破棄しようとする変数の型に依存します。引用 : PHP: unset - Manual
渡した変数を未定義にする( nullではない )にする関数のようです。
なのでこれを使えば配列の要素も削除できます。
例えば次はある配列の2番目と4番目を削除しているコード例
1 2 3 |
$ordinals = [ '1st', '2nd', '3rd', '4th', '5th' ]; unset( $ordinals[1] ); unset( $ordinals[3] ); |
このコードを実行すると要素削除後の配列の要素は [ '1st', '3rd', '5th' ] になります。
配列要素を削除するときの問題点
配列の要素を削除するとトラブルの原因になることがあります。
なぜならPHPでは配列と連想配列は全く同じものとして扱われるから
配列と連想配列が同じということについては次の記事でも詳しく解説しました。
上の記事でも結論で書いたようにPHPには配列というデータ構造は実はありません。
だから要素を削除したときにインデックスがずれてしまうという問題が発生してしまいます。
では具体的にどのいう風になるかついて例を使って説明しましょう。
例えば次のように配列の要素を削除してprint_r関数で中身を表示してみます。
1 2 3 4 |
$seasons = [ 'spring', 'summer', 'fall', 'winter' ]; unset($seasons[1]); /// 'summer' を削除 print_r($seasons); |
このコードを実行したときのprint_rの出力は次の通り
1 2 3 4 5 6 |
Array ( [0] => spring [2] => fall [3] => winter ) |
[0] => spring のあとを見てください。
[1] => fall にならずに [2] => fall とインデックス番号がそのままになっています。
これがインデックス番号がずれてしまうということです。
もしこの状態で次のように for とか while でループを回したらどうなるか・・・
1 2 3 4 5 6 7 8 9 10 |
/** forで要素を表示 */ for( $i = 0; $i < count($seasons); $i++ ){ print_r( $seasons[$i] ); } /** whileで要素を表示 */ $i = 0; while( $i < count($seasons) ){ print_r( $seasons[$i++] ); } |
当然インデックスがずれていて正しくアクセスできないのでエラーになります。
これが配列要素の削除処理をするときの厄介なところなんですよね・・・
配列には foreach を使おう
では配列のインデックスのせいでエラーが起こるときはどう対処すればいいか・・・
ということですがその対処法は for や whileを使わずに foreach をループ処理に使うことです。
foreach というのは次のようにキーと値を同時に取り出せる便利なループ構文のこと
1 2 3 |
foreach( $mixed_array as $key => $value ){ /* ループ処理 */ } |
$key => $value のように連想配列のキー( $key )と値( $value )がループ内で参照できます。
このforeach文はキーを省略して値だけを取り出すことも可能です。
なので配列要素を削除したとき、次のように使えば安全に要素にアクセス可能
1 2 3 4 5 6 7 |
$seasons = [ 'spring', 'summer', 'fall', 'winter' ]; unset($seasons[1]); /// 'summer' を削除 /** 配列の用を表示 */ foreach( $seasons as $season ){ print_r( $season . "\n"); } |
キーを省略するときは as の後に値を格納する変数を渡します。
これで次のようにエラーやバグなく期待通りに要素を取り出すことが可能
1 2 3 |
spring fall winter |
多分配列でも連想配列でもこのアクセス方法が一番安全で確実ですね。
というかそもそもPHPでは配列は連想配列の一部なので必ずforeachを使うべきです。
下手に for や while を使うとインデックス番号がずれた時に悲惨なことになるので要注意
ここまでのまとめ
ということでここまでを簡単にまとめると次の通り
- 要素の削除はunset関数を使う
この関数に渡された値は未定義(nullとは違う)の状態になる
- 配列で要素を削除するとインデックス番号がずれる
その状態で for や while を使って要素を取り出すと思わぬバグやエラーの原因に
- 安全に要素にアクセスするにはforeachを使おう!
インデックス変数を使わない foreach で要素にアクセスするのが一番安全で確実
ということで配列の要素を削除するときの注意点について解説しました。
ではではヾ(・◇・)ノ