PHP 7.2より前)は、スカラー値またはカウント不可のオブジェクトで count()
を使用すると、1
または0
を返します。
var_dump(count(123)); //int(1)
var_dump(count(new stdclass)); //int(1)
var_dump(count('hello world')); //int(1)
var_dump(count(null)); //int(0)
PHP 7.2 + )への更新では、上記のcount()
を使用すると警告メッセージが表示されます。
E_WARNINGは、count()カウント不可の型(sizeof()エイリアス関数を含む)を試みると発行されるようになりました。
警告:count():パラメーターは、Countableを実装する配列またはオブジェクトでなければなりません [sic]
その結果、多くの一般的なフレームワークはE_WARNING
を昇格させ、代わりに例外をスローします。
[ErrorException] count():パラメーターは、Countableを実装する配列またはオブジェクトでなければなりません
エラー昇格の動作については、PHP開発者がコメントしました。
警告を表示したり、より深刻なエラー/例外に変換したりする環境は影響を受けますが、これはコードのバグに注意を向けるだけです。
count()
の以前の動作は、PHP 7.2+で、E_WARNING
を出力せず、エラー報告設定を変更せず、@count()
を使用せずに達成できますか?
先ほど説明したように、count()
の元の機能を実現し、_E_WARNING
_を発行しない方法は複数あります。
PHP 7.3では、新しい関数が追加されました _is_countable
_ 、特に_E_WARNING
_の問題とis_array($var) || $var instanceof \Countable
コード内。
PHP 7.2では、数え切れないものを数えようとする際に警告が追加されました。その後、それを避けるために全員が自分のコードを検索および変更することを余儀なくされました。 :
if (is_array($foo) || $foo instanceof Countable) { // $foo is countable }
そのため、問題を解決するための最良の方法と思われる、PHPが_is_countable
_で行っているのと同じ機能を実行し、元の機能への準拠を保証するカスタム関数を作成することですcount
の。
_function countValid($array_or_countable, $mode = \COUNT_NORMAL)
{
if (
(\PHP_VERSION_ID >= 70300 && \is_countable($array_or_countable)) ||
\is_array($array_or_countable) ||
$array_or_countable instanceof \Countable
) {
return \count($array_or_countable, $mode);
}
return null === $array_or_countable ? 0 : 1;
}
_
結果:
_array: 3
string: 1
number: 1
iterator: 3
countable: 3
zero: 1
string_zero: 1
object: 1
stdClass: 1
null: 0
empty: 1
boolt: 1
boolf: 1
Notice: Undefined variable: undefined in /in/8M0Wd on line 53
undefined: 0
_
さらに、_is_countable
_を_PHP <= 7.2
_にshimできるようにして、必要な場合にのみ使用し、オーバーヘッドを最小限にします。
_if (!\function_exists('is_countable')) {
function is_countable($value)
{
return \is_array($value) || $value instanceof \Countable;
}
}
function countValid($array_or_countable, $mode = \COUNT_NORMAL)
{
if (\is_countable($array_or_countable)) {
return \count($array_or_countable, $mode);
}
return null === $array_or_countable ? 0 : 1;
}
_
count()
の機能は変更されておらず、通常は過去に警告を発していませんでした。カスタム関数を使用する代わりに、_@
_ エラー制御演算子 を使用して警告を完全に無視することもできます。
警告:このアプローチには、未定義の変数をNULL
として扱い、_Notice: Undefined variable:
_メッセージを表示しないという影響があります。
_@count($var);
_
結果:
_array: 3
string: 1
number: 1
iterator: 3
countable: 3
zero: 1
string_zero: 1
object: 1
stdClass: 1
null: 0
empty: 1
boolt: 1
boolf: 1
---
Undefined: 0
_
内部のPHP function count()
。の置き換えに関しては、PECL拡張機能APD
(Advanced PHP Debugger)があります。 _override_function
_ コアで動作するPHP関数。拡張機能名が示すように、技術的にはデバッグ用ですが、実行可能な代替手段ですカスタム関数のcount
のすべてのインスタンスを置き換えます。
_\rename_function('count', 'old_count');
\override_function('count', '$array_or_countable,$mode', 'return countValid($array_or_countable,$mode);');
if (!\function_exists('is_countable')) {
function is_countable($value)
{
return \is_array($value) || $value instanceof \Countable;
}
}
function countValid($array_or_countable, $mode = \COUNT_NORMAL)
{
if (\is_countable($array_or_countable)) {
return \old_count($array_or_countable, $mode);
}
return null === $array_or_countable ? 0 : 1;
}
_
問題は、Countableインターフェイスを実装していないスカラーまたはオブジェクトでcount()
を呼び出すと1が返されるため、バグを簡単に隠すことができるということです。
次の場合:
_function handle_records(iterable $iterable)
{
if (count($iterable) === 0) {
return handle_empty();
}
foreach ($iterable as $value) {
handle_value($value);
}
}
_
何も生成しないGeneratorを渡すと、handle_empty()
もhandle_value()
も呼び出されません。
また、どちらも呼び出されなかったという表示もありません。
デフォルトでは、これは_1
_を返しますが、さらに警告を記録します。どちらかといえば、この警告はコード内の潜在的なバグに注意を促します。
詳細については、 Counting Non-Countables を参照してください。