BLOG

ブログ

2022/05/23 技術系

【PHP】Undefined offset: 未定義の配列参照エラーについて

この記事を書いた人 T.S

こんにちは!

皆さんはPHPで配列を扱っている際に、Undefined offsetのエラーが返ってきたご経験はありますでしょうか。
私は絶賛そのエラーに遭遇したばかり! …なのですが、PHPのバージョンによってはエラーの内容が異なってくるため、あまり記憶に新しくないよ、という方もいらっしゃるかもしれません。

今回は、Undefined offsetが発生する原因に加えて、PHPのバージョンごとに異なる挙動の差についてまとめてみました。

『Undefined offset』の原因

array 型の変数に対して、『存在しないインデックスの要素』にアクセスしようとしているため発生します。

$test_array = array("test0", "test1");  // array型

var_dump($test_array[2]);

出力結果(PHP 7.4.0 の場合)

Notice: Undefined offset: 2

上の例では、配列のインデックスの0・1はそれぞれ値が定義されていますが、2は未定義のためエラーとなっています。

ちなみに、配列のキーについては型キャストが行われているようで、以下どちらの記述でも、int 型として扱われるようです👀

var_dump($test_array[2]);
var_dump($test_array["2"]);

key は、整数 または 文字列です。
さらに、次のような key のキャストが発生します。

10 進数の int として妥当な形式の String は、 数値の前に + 記号がついていない限り、 int 型にキャストされます。 つまり、キーに “8” を指定すると、実際には 8 として格納されるということです。

PHPマニュアル:配列

『Undefined offset』にまつわるエラーの話

Notice: Undefined offsetですが、PHP 8以降だと、Warning:Undefined array keyとなり、エラーレベル・エラー文が変更されています。

このように、PHPのバージョンによっては挙動が異なることがあります。また、未定義の配列要素の参照元について、型が異なればエラーも異なってきます。その違いを知るため、「PHPバージョンの差によるエラーの違い」と「参照元の型の差によるエラーの違い」を確認してみました。

挙動の確認には、「PHP Sandbox」というPHPテストサイトを使用しました。

こちらのサイトではPHPのバージョンを指定して、コードの実行・結果確認ができます!バージョンを同時実行することも可能なので、実行結果を比較したい!という場合も便利です✨

array型:未定義の配列インデックスを参照した場合

$test_array = array("test0", "test1");   // array型

var_dump($test_array[2]);

実行結果

// PHP 7.2.0, PHP 7.4.0
Notice: Undefined offset: 2
NULL

// PHP 8.0.0
Warning: Undefined array key 2
NULL

PHP 8 では、Warning: Undefined array key と、エラーレベル・エラー文言が変更になっています。エラーレベルが通知(Notice)から警告(Warning)に上がっており、いずれ警告からエラーに段階が上がることも考えられるため、Undefined offset もしくはUndefined array key が発生している箇所は、早めに解消していた方が良さそうです…!

array型以外:未定義の配列インデックスを参照した場合

$test_null = NULL;   // NULL型

var_dump($test_null[2]);

実行結果

// PHP 7.2.0
NULL

// PHP 7.4.0
Notice: Trying to access array offset on value of type null
NULL

// PHP 8.0.0
Warning: Trying to access array offset on value of type null
NULL

PHP 7.4.0 より前のバージョンでは、array 型以外の変数に対して、未定義の配列要素を参照してもエラーは発生しませんでした。しかし、PHP 7.4.0 以降は、「array 型以外の値に、配列参照しようとしてるけど…」といったメッセージが返却されるため、参照元の型には注意が必要そうです。

例ではNULL 型で記述していますが、int 型・bool 型の変数を対象に実行した場合も、同様のエラーが発生します(その際は、上記エラー文言のtype部分が、それぞれ intboolになります)

string型:未定義の配列インデックスを参照した場合

$test_string = 'string';  // string型

var_dump($test_string[2]);

実行結果

// PHP 7.2.0, PHP 7.4.0, PHP 8.0.0
string(1) "r"

string型の変数に対して、配列のインデックスを参照するように記述すると、文字列内の任意の文字にアクセスすることができます。

$str[42] のように、 角括弧を使用してゼロから始まるオフセットを指定すると、 文字列内の任意の文字にアクセスし、修正することが可能です。 つまり、文字列を文字の配列として考えるわけです。

PHPマニュアル:文字列

ちなみに、範囲外のインデックスを指定すると、PHP7 ではNotice: Uninitialized string offset のエラーが発生します(PHP8 だとWarning になります)

まとめ

今回は、Undefinend offsetをはじめとした、未定義の配列エラーについて紹介しました。

エラーの回避方法については割愛させていただきましたが、isset関数array_key_exists関数の使用が良いみたいです✨(どちらも配列の要素やキーの存在チェックが効果的みたいですね)

「未定義の値参照を回避するためにも、配列の要素を雑に指定しないこと」は勿論!実行するPHPのバージョンによってはエラーが発生しない、などの差もあるため、「しっかりと実行環境の意識をすること」も大事だなと改めて感じました。



株式会社ウイングドアは福岡のシステム開発会社です。
現在、私達と一緒に"楽しく仕事が出来る仲間"として、新卒・中途採用を絶賛募集しています!
ウイングドアの仲間達となら楽しく仕事できるかも?と興味をもった方、
お気軽にお問い合わせ下さい!

アーカイブ