PHP foreach() argument must be of type array|object, null given の原因と解決方法【PHP8のnull対策】

PHP Warning: foreach() argument must be of type array|object, null givenとは?ざっくりと3行で
  • PHP Warning: foreach() argument must be of type array|object, null givenは、配列やオブジェクトのはずの変数がnullのままforeachに渡されたときに発生する警告だ。
  • 実務では関数やDBクエリの戻り値がnullだったり、未定義の変数をそのまま回そうとしたケースが大半で、配列だと思い込んでいた変数の中身がnullだったというのが実態だ。
  • foreachに渡す前に ?? [] で空配列を用意するか、is_array() で中身を確かめれば、ループはスキップされ警告も消える。
配列だと思った変数がnullでforeach() argument must be of type array|object, null givenが出て?? []で直す4コマ
①ログにforeachの警告が出て焦る。②変数を確認すると中身がnullだと判明する。③戻り値に?? []を足して空配列へ変換する。④警告が消えnullチェックを習慣にすると決める。

この4コマは、PHP Warning: foreach() argument must be of type array|object, null givenが実際の開発でどう現れるかを再現したケーススタディです。ログに突然赤い警告が出て、コード自体は正しく見えるのに原因が掴めない、という状況は多くのPHP開発者が通る道になります。ポイントは、foreachの書き方が悪いのではなく、渡している変数の中身がnullになっているという点にあります。

2コマ目のように var_dump() で型を確認すると、配列だと思っていた変数がNULLだと一目でわかります。関数の戻り値やAPIレスポンスは、データが0件のときに空配列ではなくnullを返す設計になっていることが珍しくありません。ここを見落とすと、開発環境では気づかず本番でだけ警告ログが大量に積み上がることもあります。

3コマ目の ?? [] は、nullのときだけ空配列に置き換える最短の対処です。空配列ならループは0回で終わり、警告は発生しません。表示は崩れないため軽視されがちですが、放置するとログが警告で埋まり、本当に重要なエラーが埋もれるリスクにつながります。早めに潰しておく価値がある警告だと言えます。

PHP Warning: foreach() argument must be of type array|object, null givenの基本情報

PHP Warning: foreach() argument must be of type array|object, null givenは、foreachに渡す対象が配列でもオブジェクトでもなく、nullだったときにPHP 8が出力する警告です。まずは正体を表で整理します。

項目内容
エラーメッセージWarning: foreach() argument must be of type array|object, null given in /path/to/file.php on line NN
発生する言語・環境PHP 8.0 / 8.1 / 8.2 / 8.3(PHP 8.0以降)。エラーレベルはE_WARNING
エラーの意味foreachにはarrayかobjectを渡す必要があるのに、実際にはnullが渡された
主な原因配列を返すはずの関数・DBクエリ・APIレスポンスがnullを返した、または変数が未定義だった
解決の基本方針foreachの直前で ?? [] やis_array()を使い、nullを空配列に置き換える
ITKAGYO運営者デプロイ太郎のアイコン画像

画面表示は崩れないのにログだけ真っ赤、というパターン、地味に焦りますよね。落ち着いて変数の中身を確認すれば、原因はだいたい一本道です。

なぜPHP Warning: foreach() argument must be of type array|object, null givenは発生するのか?

意外に思われがちですが、このエラーはforeachの構文ミスではありません。foreach自体は正しく、渡している変数がnullになっている点が真犯人です。PHP 8ではnullを渡すとE_WARNINGになりますが、処理は止まらずループがスキップされるため、気づきにくいのが厄介な特徴です。

PHP Warning: foreach() argument must be of type array|object, null givenの原因は、値が「どこでnullに化けたか」で切り分けると整理しやすくなります。ここでは発生箇所ごとに、戻り値・未定義変数・ネストしたキーの3パターンで見ていきます。

原因パターン1:関数やDBクエリの戻り値がnullだった

最も多いのが、配列を返すはずの関数がデータ0件のときにnullを返しているケースです。呼び出し側は配列前提でforeachを書いているため、そのまま警告になります。

<?php
// PHP 8.3
function getUsers(): ?array {
    return null; // 該当データが無いときにnullを返す実装になっている
}

$users = getUsers();        // $users には null が入る
foreach ($users as $user) { // Warning: foreach() argument must be of type array|object, null given
    echo $user;
}

getUsers() の戻り値型が ?array になっており、nullを返し得る点が原因です。呼び出し側では、戻り値をnull合体演算子で空配列に受け直すと安全になります。

<?php
// PHP 8.3
$users = getUsers() ?? []; // null なら空配列にフォールバックする
foreach ($users as $user) { // 空配列ならループは0回で、警告は出ない
    echo $user;
}

原因パターン2:変数が未定義のままforeachに渡された

条件分岐の中だけで変数へ代入し、条件を満たさなかった経路で未定義になるパターンです。PHP 8では未定義変数はnull扱いとなり、そのままforeachへ流れ込みます。

<?php
// $items は if の中でしか代入されていない
if (isset($_GET['on'])) {
    $items = ['りんご', 'みかん'];
}
foreach ($items as $item) { // 未定義のとき $items は null 扱い → null given
    echo $item;
}

この場合、PHP 8では先にUndefined variableの警告が出て、続けてforeachのnull givenが出ます。対策はシンプルで、分岐の前に空配列で初期化しておくだけです。未定義変数の詳細は PHP Undefined index/variable の原因と解決方法 も参考になります。

<?php
$items = []; // 先に空配列で初期化しておく
if (isset($_GET['on'])) {
    $items = ['りんご', 'みかん'];
}
foreach ($items as $item) { // $items は必ず配列なので安全
    echo $item;
}

原因パターン3:ネストした配列のキーがnullだった

APIレスポンスや多次元配列で、親の配列は存在するのに中のキーがnullというケースです。$response['data'] がnullのままforeachに渡ると発生します。

<?php
// APIレスポンスを配列にデコードした例
$response = ['status' => 'ok', 'data' => null]; // 該当0件で data が null
foreach ($response['data'] as $row) { // null given
    echo $row['name'];
}

ここでは data キーそのものは存在するため、キー未定義とは別問題です。取り出した値を ?? [] で受け、必要ならis_arrayで二重に確認します。キーの有無が絡む警告は PHP Warning: Undefined array key の原因と解決方法 と合わせて押さえておくと理解が深まります。

<?php
$rows = $response['data'] ?? []; // null を空配列に置き換える
if (is_array($rows)) {           // 念のため配列かどうかも確認
    foreach ($rows as $row) {
        echo $row['name'];
    }
}
foreachのnull警告の原因を解説するデプロイ太郎のアイコン画像

パターン1の「戻り値がnull」は本当によく見かけます。関数の型が?arrayになっていたら、呼び出し側で?? []を足す習慣をつけておくと楽ですよ。

PHP Warning: foreach() argument must be of type array|object, null given はPHPのバージョンでどう変わる?

PHP Warning: foreach() argument must be of type array|object, null givenは、実はPHP 8で文言が刷新されたメッセージです。同じ原因でもバージョンによって表示が変わるため、検索や調査の前に確認しておく価値があります。

実行環境表示されるエラーメッセージ
PHP 8.0 〜 8.3Warning: foreach() argument must be of type array|object, null given
PHP 7.x 以前Warning: Invalid argument supplied for foreach()

PHP 8では、渡した値の型に応じてメッセージ末尾が変化します。nullなら null given、false等なら bool given、文字列なら string given、整数なら int given と表示されます。どちらのバージョンでもエラーレベルはE_WARNINGで、スクリプトは停止せずループがスキップされる挙動は共通です。

LaravelやWordPressでforeach() argument must be of type array|object, null givenが出るのはなぜ?

Laravelでの発生パターン

Laravelでは、session() やリクエスト、Eloquentの一部メソッドがnullを返す場面でforeachのnull givenが起きます。特に session('cart') のようにデフォルト値を省略すると、データが無いときnullが返り、Blade側の @foreach で警告になります。get() はコレクションを返しますが、first() やセッション値はnullになり得る点に注意が必要です。

<?php
// Laravel 11 / コントローラやBladeでの例
// session('cart') はカートが空だと null を返す
$cart = session('cart'); // null の可能性がある
foreach ($cart as $item) { // Warning: ... null given
    echo $item['name'];
}

// 修正: 第2引数にデフォルトの空配列を渡す
$cart = session('cart', []); // null を返さなくなる
foreach ($cart as $item) {
    echo $item['name'];
}
Bladeでは @forelse?? [] を組み合わせると、空データやnullでもレイアウトを崩さず安全に描画できます。

WordPressでの発生パターン

WordPressでは、ACFの get_field() が値なしでfalseやnullを返す、あるいはテーマ関数が想定外の値を返す場面でforeachのnull givenに遭遇します。取得系関数は成功時に配列を返しても、失敗時はfalseやnullを返す仕様のものが多く、戻り値をそのまま回すと危険です。

<?php
// WordPress / ACFのリピーターフィールド例
// get_field() は値が無いと false や null を返す
$rows = get_field('gallery'); // null の可能性がある
foreach ($rows as $row) {     // Warning: ... null given
    echo $row['image'];
}

// 修正: 取得結果を is_array で受けてから回す
$rows = get_field('gallery');
if (is_array($rows)) {
    foreach ($rows as $row) {
        echo $row['image'];
    }
}
get_the_terms()get_posts() は失敗時にfalseやWP_Errorを返すため、is_array()で受けてから回すと事故を防げます。

「null given」以外の型で出るforeach()警告への対処は?

PHP Warning: foreach() argument must be of type array|object, null givenは、渡した値の型によって末尾が変わります。ここでは実務で頻出する2つのバリエーションを取り上げます。

「bool given(false given)」と出る場合

WordPressの get_the_terms() のように、失敗時にfalseを返す関数の戻り値を回すと bool given になります。false・nullの両方を空配列に落とす書き方が有効です。

<?php
$terms = get_the_terms($post_id, 'category'); // 該当なしで false を返す
foreach (($terms ?: []) as $term) { // false や null を空配列に置き換える
    echo $term->name;
}

「string given」と出る場合

本来は配列に分割するはずの文字列を、そのままforeachに渡すと string given になります。PHPは文字列を自動でループ対象にはしないため、明示的に配列へ変換します。

<?php
$csv = '1,2,3';         // 本来 explode するはずが文字列のまま
// foreach ($csv as $n) {} // これは string given になる
foreach (explode(',', $csv) as $n) { // 配列に変換してから回す
    echo $n;
}

PHP Warning: foreach() argument must be of type array|object, null given はどうデバッグすればいい?

PHP Warning: foreach() argument must be of type array|object, null givenのデバッグは、まず警告に書かれたファイル名と行番号を確認し、その行でforeachに渡している変数の型を調べるのが近道です。var_dump(gettype($変数)) でNULLが出れば、原因はその変数を用意した処理にあると特定できます。

<?php
$data = getSomething();
var_dump(gettype($data)); // NULL と出れば戻り値が原因

if (!is_iterable($data)) { // 配列でもオブジェクトでもない場合
    error_log('foreach対象がiterableではありません: ' . gettype($data));
    $data = []; // 空配列に補正してループへ
}
foreach ($data as $row) {
    // 処理
}
foreachのnull警告をデバッグするコツを話すデプロイ太郎のアイコン画像

行番号は警告がちゃんと教えてくれます。あとはその1行の変数をvar_dumpするだけ。犯人探しは意外とあっさり終わることが多いです。

PHP Warning: foreach() argument must be of type array|object, null given を未然に防ぐには?

PHP Warning: foreach() argument must be of type array|object, null givenの予防は、そもそもnullをforeachに近づけない設計が基本になります。戻り値の型を ?array ではなく array にして、常に配列を返すよう統一しておくと、呼び出し側のチェックそのものが不要になります。

<?php
declare(strict_types=1);

// 戻り値を常に array にして null を返さない設計にする
function getTags(): array {
    $rows = fetchTags(); // 何らかの取得処理
    return $rows ?? [];  // null なら空配列に整えてから返す
}

foreach (getTags() as $tag) { // null が来ないので警告は発生しない
    echo $tag;
}
?arrayのようなnullを許す戻り値型を避け、常に配列を返す設計にすると、foreach側の防御コードを減らせます。

PHP7とPHP8でforeachのnull警告はどう違うのか?

PHP Warning: foreach() argument must be of type array|object, null givenは、PHP 8.0でメッセージ文言が全面的に書き換えられた警告です。PHP 7以前は Invalid argument supplied for foreach() という抽象的な文言で、何が渡されたのかまでは示されませんでした。PHP 8では array|object を期待している事実と、実際に渡された型(null given など)まで明示されるため、原因の特定が格段に速くなっています。

挙動面では、どちらのバージョンもエラーレベルはE_WARNINGで、警告を出しつつループはスキップされ、スクリプトは停止しません。ただしPHP 8では未定義変数がNoticeからWarningへ格上げされたため、未定義変数由来のnull givenは警告が二重に出て目立ちやすくなったという違いがあります。nullそのものの扱いに不安があれば NULLとは?意味をスラング・IT両方からわかりやすく解説 も一読しておくと理解が固まります。

PHP8で変わったforeach警告への向き合い方を励ますデプロイ太郎のアイコン画像

PHP 8はメッセージが親切になった分、警告の数も増えて驚くかもしれません。でも一つずつ潰せば必ず消えます。焦らずいきましょう!

よくある質問

Q
この警告が出てもプログラムは止まりますか?
A

止まりません。このメッセージはE_WARNINGレベルで、foreachのループがスキップされるだけで後続の処理は続行されます。ただし表示が崩れなくてもログには警告が残り続けるため、放置せず原因を潰しておくのが望ましいです。

Q
本番環境で画面に警告を出さないようにするには?
A

本番では display_errors をOffにし、log_errors をOnにしてログへ記録する運用が基本です。ただしこれは表示を隠すだけで根本解決ではないため、ログを監視して ?? [] やis_arrayで原因を直すことが前提になります。

Q
Laravelで同じ警告が大量に出ます。どこから直せばいい?
A

まずログの行番号からnullになっている変数を特定してください。Laravelでは session() やリクエスト値、Eloquentの first() がnullを返しやすいので、そこに ?? [] やデフォルト値を与えると多くが解消します。Blade側は @forelse の活用も有効です。

Q
PHPStanなどの静的解析で事前に防げますか?
A

防げます。PHPStanやPsalmは、?array のようにnullを返し得る値をチェックせずにforeachへ渡している箇所を実行前に警告してくれます。CIに組み込んでおけば、null givenが本番で出る前にコードレビュー段階で潰せます。

Q
foreach() argument must be of type array|object, null given と Invalid argument supplied for foreach() の違いは何ですか?
A

両者は同じ問題を指す、PHPバージョン違いのメッセージです。Invalid argument supplied for foreach() はPHP 7以前の古い文言で、foreach() argument must be of type array|object, null given はPHP 8.0以降の新しい文言になります。後者は期待する型と渡された型まで明示するため、原因の特定がしやすくなっています。

この記事と一緒に知っておきたいエラー解決

関連エラー この記事との関連
PHP Warning: Undefined array key の原因と解決方法 未定義キーがnullとして評価され、そのままforeachへ渡ると本エラーに繋がるため。
PHP Undefined index/variable の原因と解決方法 未定義変数がnull扱いになる仕組みを理解すると、原因パターン2の予防に直結するため。
PHP Fatal error: Call to a member function on null の原因と解決方法 nullをそのまま操作して起きる、同じ根っこを持つ代表的な落とし穴のため。
Java NullPointerException の原因と解決方法 言語は違えど、nullを扱い損ねて起きるエラーの考え方を比較できるため。
NULLとは?意味をスラング・IT両方からわかりやすく解説 そもそもnullとは何かを押さえると、警告の本質的な理解が深まるため。

【出典】参考URL

https://www.php.net/manual/en/control-structures.foreach.php :foreachが受け付ける型(array・object)と挙動の一次情報
https://php-errors.readthedocs.io/en/latest/messages/foreach()-argument-must-be-of-type-array%7Cobject.html :PHP 8での新メッセージ文言とエラーレベルの確認
https://php-errors.readthedocs.io/en/latest/messages/invalid-argument-supplied-for-foreach().html :PHP 7以前の旧メッセージ文言の確認

コメント

デプロイ太郎のSNSを見てみる!!