警告の内容エラーログを確認していると、警告の山に遭遇することがあります。42行目で「Warning: Invalid argument supplied for foreach()」と表示されています。これはPHPにおける典型的な悩みの一つです。通常、これは配列やオブジェクトではない変数をループ処理しようとしていることを意味します。
なぜこのエラーが発生するのかforeach構造は厳格です。array(配列)またはTraversableインターフェースを実装したobject(オブジェクト)を必要とします。null、string(文字列)、またはboolean(真偽値)を渡すと、PHPは処理を中断し、この警告をスローします。これは、データを返すと期待していた関数が失敗し、代わりにfalseを返した場合によく発生します。
実例- データベースクエリが空: 条件に一致する行がなかったため、PDO::fetch()がfalseを返した。- APIレスポンスの破損: 外部サービスが有効なJSONではなくHTMLの404ページを送信したため、json_decode()がnullを返した。- スキップされたロジック: 一度も実行されなかったif文の中でのみ変数が初期化された。- 未初期化の変数: 配列として宣言されていない変数を参照した。## エラーの解決方法### 1. null合体演算子を使用する(PHP 7以降に最適)??演算子は、モダンなコードにおいて最もクリーンな解決策です。変数が存在しない、あるいはnullの場合に、即座に空のフォールバック配列を提供できます。
// より安全な方法:
foreach ($users ?? [] as $user) {
echo $user['name'];
}
2. クイック配列キャスト変数を強制的に反復可能な形式にしたい場合は、キャストを使用します。これにより、nullは空の配列に、単一の文字列はその文字列を含む配列に変換されます。
// 入力が常に反復可能であることを保証する
foreach ((array)$userData as $item) {
process($item);
}
警告:真偽値には注意してください。falseをキャストすると[false]になり、役に立たない値でループが1回実行されてしまいます。
3. is_iterable()による防御的チェック複雑なロジックの場合は、is_iterable()(PHP 7.1以降で利用可能)を使用します。これは、ループ可能なオブジェクトも考慮するため、is_array()よりも堅牢です。
if (is_iterable($products)) {
foreach ($products as $product) {
echo $product->title;
}
} else {
// 「データなし」の状態を適切に処理する
echo "利用可能な製品はありません。";
}
4. 最初から空の変数を用意するスクリプトの開始時に変数を初期化することで、エラーを防ぎます。これにより、たとえ中身が空であっても、ループは常に参照できる対象を持つことになります。
$results = []; // 早期に初期化
if ($searchActive) {
$results = $db->getResults() ?: []; // falseの場合は空の配列を代入
}
foreach ($results as $row) {
// ここで警告は発生しません
}

