PHPで配列やCountableオブジェクトの要素数を取得するcount関数。しかし、引数がnullの場合にどうなるかを正確に知っている人は意外と少ないはずです。PHPのバージョンによって返り値やエラーレベルが異なり、書き方を間違えるとWarningや致命的なエラーになることがあります。この記事では、count関数にnullを渡したときの挙動、0を返す条件、そして最新のバージョンで安全に使うためのポイントまで詳しく解説します。
目次
PHP count 関数 null の挙動概要
まずPHPのcount関数にnullを渡した場合の基本的な挙動を理解することが重要です。PHPのバージョンごとに挙動が異なり、Warningを出すか、TypeErrorで止まるか、あるいは単に0を返すかという3つのパターンがあります。これを把握しないと、コードの互換性やエラー処理に大きな混乱を招きます。
PHP 5〜7.1 の挙動
古いPHPバージョン(PHP 5.x~PHP 7.1)では、count(null)を実行すると異なる型が許容されるため、Warningは出さずに0を返す、または非配列・非Countableな値を1として数えることもありました。nullの場合は0が返されるのが一般的です。
PHP 7.2〜7.4 の挙動
PHP 7.2以降では、count関数に対してnullなど非配列/非Countableな値を渡した際にE_WARNINGが発生し、返り値は0となることが標準化されています。つまり静かに数えるだけでなく、Warningを記録するコード診断が可能になったということです。
PHP 8 の挙動
最新のPHPバージョンでは、countにnullを渡すとTypeErrorがスローされ、プログラムはそこで停止します。ただし配列キャスト((array))やis_countable関数などで事前チェックすれば安全に0を取得できます。
PHP count 関数 null を使うときに起こる問題と原因分析
count(null)による問題は主に「Warningが出ること」「動作がバージョンに依存すること」「TypeErrorで致命的になること」の三つです。これらの問題を理解しなければ、アップグレードや運用中のアプリケーションで予期しない障害を引き起こします。ここではそれぞれの原因を掘り下げます。
Warningの発生条件
PHP 7.2~7.4では、count関数にnullを渡すと配列やCountableでない型が引数として渡された際にWarningが発生します。これはcount関数が「配列またはCountableなオブジェクト」での呼び出しを想定しており、nullはそれに該当しないためです。nullだけでなく文字列や数値を渡しても同様のWarningが出るケースがあります。
動作のバージョン依存性
PHPのバージョンごとにcount(null)の挙動は異なります。PHP 5~7.1ではQuietに0を返すことが多く、PHP 7.2~7.4ではWarningを出して0を返す。PHP 8以降ではTypeErrorとなる。つまり、どのバージョンで動かすかに注意し、コードをその影響下でテストする必要があります。
TypeErrorによる致命的エラーになる場合
PHP 8以降では、count関数のパラメータが期待される型(配列またはCountable)でない場合、WarningではなくTypeErrorが発生します。nullはこのケースに該当し、エラーが咎められます。このため、nullかどうかを事前にチェックしなければ、実行時にスクリプトが停止する恐れがあります。
PHP count 関数 null に対して0を返す条件
countにnullを渡したときに0を返すのはどのような条件下かを知ることは、アップグレード時やコードを移植する際に非常に役立ちます。バージョンとエラーレベル設定、そして入力値の状況の三要素が鍵を握ります。
エラーレベル設定がWarningを抑制している場合
PHPの設定でWarningを非表示にしている(error_reportingの設定やdisplay_errorsがオフなど)場合、Warningが発生していても画面上には見えず、動作としては0を返すコードが「正常に動くように見える」ことがあります。ただしログにはWarningが残ることが多いため、潜在的な問題として無視できません。
nullが明示的に渡されていて配列キャストがされている場合
(array)null のようにキャストしてからcountを呼ぶと、nullが空の配列として扱われて0を返します。PHPはキャストされた後は配列と判断するためです。この手法はPHPのどのバージョンでも比較的安全であり、TypeErrorを回避する手段として頻繁に用いられます。
is_countable関数を使ってCountableオブジェクトまたは配列か確認している場合
PHP 7.3から導入されたis_countable関数により、引数が配列またはCountableインターフェースのオブジェクトかどうかを確認できます。このチェックを行った後でcountを呼べば、nullや不正な型に対して0を安全に返すロジックを構築できます。
PHP count 関数 null を安全に使うためのベストプラクティス
nullが来る可能性がある変数をcountで扱う場合、実装方法によってWarningやTypeErrorを避けることができます。ここでは最新のPHP環境でも安心して使えるコーディングパターンを紹介します。
is_countableを使った前提チェック
まずは変数が配列かCountableであるかを確認する方法です。こうすることで、nullや文字列などを誤ってcountに渡してしまう状況を避けられます。以下のようなコードが推奨されます。
if (is_countable($var)) {
$cnt = count($var);
} else {
$cnt = 0;
}
この構造により、nullの場合はelseに回って0が安全に返されます。
null合体演算子または配列キャストを使う方法
null合体演算子(??)を使ってデフォルト値を空配列にする方法や、(array)キャストを使って変数を強制的に配列扱いにする方法が有効です。例えば以下のように書くと警告やエラーを防げます。
$cnt = count($var ?? []);
$cnt = count((array)$var);
このような書き方はPHP 7以降のバージョンで広く使われており、最新のPHPでも有効です。
strict typesや型宣言を利用する
関数の引数に型宣言を付けて、配列またはCountableのみを受け付けるようにするとコードの安全性が上がります。nullを許容したい場合はnullable型を使います。こうした設計をしておくことで、countにnullが誤って渡る状況をそもそも設計段階で制御できます。
バージョン別挙動の比較
PHPのバージョンごとのcount(null)の挙動を一覧にするとわかりやすいため、以下の表で整理します。
| PHP バージョン | count(null) 実行時の結果 | エラー/Warning/例外 |
|---|---|---|
| PHP 5.x ~ 7.1 | 0 を返すことが多い | 通常は警告なし |
| PHP 7.2 ~ 7.4 | 0 を返す | E_WARNINGが発生 |
| PHP 8.0 以降 | 未指定型を強制的に配列/Countableとしない限り、CountTypeError例外が発生 | TypeErrorがスローされる |
実践コード例と問題解決のシナリオ
ここでは実際にnullを渡したときのコード例と、それに対応する解決策をいくつか紹介します。若い開発者からベテランまで参考になるように、多様なケースを取り上げます。
例1:直接count(null)を呼び出してしまっている場合
問題のコード:
$var = null;
echo count($var);
PHP 8ではこれがTypeErrorになるため致命的です。PHP 7.2~7.4ではWarningとともに0が返ります。事前チェックがないと不具合の元になります。
例2:null合体演算子を使って防ぐ方法
以下のように書くことでnullのときの安全性を確保できます。
$cnt = count($var ?? []);
echo $cnt;
このようにすると、$varがnullあるいは未定義であっても空配列扱いされ、Warningや例外を回避して0が返ります。
例3:(array)キャストを使う方法
配列キャストを利用する方法も広く使われています。
$cnt = count((array)$var);
こう書くと$varがnull、文字列、数値などであっても強制的に配列に変換され、要素が0個の配列として扱われるため、Warningや例外を発生させずに0が返ります。
まとめ
count関数にnullを渡したときの挙動はPHPのバージョンによって異なります。PHP 5〜7.1では静かに0を返す、安全性の高い挙動をしますが、PHP 7.2〜7.4ではWarningが発生しつつ0を返し、PHP 8以降ではTypeErrorが発生して処理が停止する可能性があります。
安全に扱いたいなら、is_countableによるチェック、null合体演算子や( array )キャストによるデフォルトの空配列化、型宣言とnullable型の適切な設計が必須です。
この記事で紹介したパターンを使えば、バージョンを問わずcount関数 nullの問題を回避しつつ0を返す処理が実装でき、予期しないエラーやWarningに悩まされることが少なくなるでしょう。
コメント