下位互換性のない変更点
関数に渡す引数が少ない場合の挙動
これまでのバージョンでは、ユーザー定義の関数に渡す引数が足りない場合は warning が発生していました。PHP 7.1 以降では、warning ではなく Error 例外が発生するようになります。 この変更はユーザー定義の関数に対してだけのもので、 内部関数には影響を及ぼしません。
<?php
function test($param){}
test();
上の例の出力は、 たとえば以下のようになります。
Fatal error: Uncaught ArgumentCountError: Too few arguments to function test(), 0 passed in %s on line %d and exactly 1 expected in %s:%d
スコープを調べる関数の動的呼び出しの禁止
ある種の関数について、動的な呼び出し
($func()
や array_map('extract', ...)
のような形式)
が使えなくなりました。対象になるのは、別のスコープを調べたり変更したり、
あいまいな挙動になってしまったりするような関数です。
この変更の影響を受ける関数は、以下のとおりです。
- assert() - 最初の引数に文字列を渡した場合
- compact()
- extract()
- func_get_args()
- func_get_arg()
- func_num_args()
- get_defined_vars()
- mb_parse_str() - 引数が一つだけの場合
- parse_str() - 引数が一つだけの場合
<?php
(function () {
$func = 'func_num_args';
$func();
})();
上の例の出力は以下となります。
Warning: Cannot call func_num_args() dynamically in %s on line %d
数値形式文字列の変換が科学記法に対応
数値形式の文字列の演算や型変換が、科学記法に対応するようになりました。
(int)
によるキャストや、
intval() (基数が10の場合)、
settype()、decbin()、
decoct()、dechex() といった関数もその対象です。
mt_rand() のアルゴリズムの修正
mt_rand() のデフォルトが、修正版のメルセンヌ・ツイスタ
アルゴリズムを使うようになりました。mt_rand()
の結果に依存するコードを書いていた場合は、mt_srand()
のオプションの第二引数に MT_RAND_PHP
を指定すると、これまでの挙動 (間違った実装) を維持できます。
rand() と srand() が、 それぞれ mt_rand() と mt_srand() のエイリアスとなる
rand() と srand() は、それぞれ mt_rand() と mt_srand() のエイリアスになりました。つまり、 rand()、shuffle()、 str_shuffle()、array_rand() の出力がこれまでのバージョンとは変わるということです。
ASCII 制御文字 delete は識別子として使えない
ASCII 制御文字 delete (0x7F
) は、
クォートしない限りは識別子として使えなくなりました。
error_log
に syslog
を指定した場合の変更
INI 項目 error_log
の設定値を
syslog
にした場合に、PHP のエラーレベルが syslog
のエラーレベルにマッピングされるようになりました。
これまでのバージョンではすべてのエラーが notice レベルで記録されていましたが、
この変更によって、今までよりも細やかな区別ができるようになります。
未完成のオブジェクトのデストラクタは呼び出されない
オブジェクトのコンストラクタの実行中に例外がスローされた場合に、 そのオブジェクトのデストラクタが呼ばれることはなくなりました。 以前のバージョンでは、場合によっては (例: そのオブジェクトが例外バックトレースなどで外部から参照される場合) デストラクタが呼ばれることもありました。
参照渡しの引数の call_user_func() での扱い
引数を参照渡しで受け取る関数を call_user_func() から呼んだときに、例外が発生するようになりました。 以前のバージョンでは、完全修飾形式の呼び出しであるか否かによってこの場合の挙動が異なっていました。
さらにこの場合、call_user_func() や call_user_func_array() は関数呼び出しを中断しなくなりました。 "expected reference" という警告は出すものの、処理自体はそのまま続行します。
文字列における空のインデックス演算子はサポートしない
文字列に空のインデックス演算子を適用する (例: $str[] = $x
)
と、fatal エラーが発生します。これまでのバージョンではエラーにならず、
ただ配列に変換されるだけでした。
空文字列に対して、文字列インデックス経由で値を設定する操作
空文字列に対して、一文字単位で変更する操作が、 空でない文字列と同じように機能するようになりました。 つまり、範囲外のオフセットに対する書き込みがスペースで埋められ、 整数型でない値は整数に変換され、最初の文字だけが採用されるというものです。 これより前のバージョンでは、黙って空の配列として扱われていました。
<?php
$a = '';
$a[10] = 'foo';
var_dump($a);
?>
上の例の PHP 7.0 での出力は、このようになります。
array(1) { [10]=> string(3) "foo" }
上の例の PHP 7.1 での出力は、このようになります。
string(11) " f"
削除された INI 項目
以下の INI 項目は、削除されました。
-
session.entropy_file
-
session.entropy_length
-
session.hash_function
-
session.hash_bits_per_character
参照による代入で自動的に作られる配列の要素の並び順の変更
参照による代入で配列の要素が自動的に作られる場合に、その並び順が変更されました。
<?php
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
?>
上の例の PHP 7.0 での出力は、このようになります。
array(2) { ["a"]=> &int(1) ["b"]=> &int(1) }
上の例の PHP 7.1 での出力は、このようになります。
array(2) { ["b"]=> &int(1) ["a"]=> &int(1) }
同値な要素の並び順
内部的なソートアルゴリズムが改良されたことに伴って、 比較したときに等しいとみなされる要素の並び順が以前とは変わるかもしれません。
注意:
同値な要素の並び順に依存するコードは書かないようにしましょう。 その並び順がいつまでも同じであるとは限りません。
E_RECOVERABLE エラーのエラーメッセージ
E_RECOVERABLE エラーのエラーメッセージが、 "Catchable fatal error" から "Recoverable fatal error" に変更されました。
unserialize() 関数の $options パラメータ
unserialize() 関数の $options パラメータの
allowed_classes
要素が、
型を厳密に解釈するようになりました。
つまり、array または bool
以外のあらゆる値が与えられても、
unserialize() は false
を返し、
E_WARNING
レベルの警告が発生します。
DateTime クラスのコンストラクタに、マイクロ秒も組み込まれる
DateTime と DateTimeImmutable
は、現在時刻、明示的な時刻、
または相対時刻を示す文字列
(例: "first day of next month"
)
から構築されると、
マイクロ秒を適切に含めるようになりました。
これは、新しく生成されたふたつのインスタンスが、true
ではなくて
false
を返しやすくなったということです。
<?php
new DateTime() == new DateTime();
?>
致命的なエラーが Error 例外に変換される
Date 拡張モジュールでは、 DateTime または DatePeriod クラス のシリアライズデータが不正だったり、 シリアライズしたデータからタイムゾーンを初期化するのに失敗した場合、 致命的なエラーにならず、 __wakeup() や __set_state() メソッドから Error 例外をスローするようになりました。
DBA 拡張モジュールでは、 (dba_insert() のように) データを変更する関数は、キーが正確にふたつの要素を含んでいない場合に キャッチ可能な fatal error ではなく、 Error 例外をスローするようになりました。
DOM 拡張モジュールでは、 不正なスキーマ や RelaxNG検証コンテキスト は 致命的なエラーにならず、 Error 例外をスローするようになりました。 同じように、適切な基底クラスを継承しないノードクラスを登録しようとしたり、 不正なプロパティを読み出そうとしたり、 読み込み専用のプロパティに書き込もうとしたりしても、 同様に Error 例外をスローようになりました。
IMAP 拡張モジュールでは、 16385 バイト以上の email アドレスは、 致命的なエラーにならず、 Error 例外をスローするようになりました。
Intl 拡張モジュールでは、 Collator クラスを継承したクラスで、 親メソッドを呼ぶ前に親のコンストラクタを呼ぶのに失敗すると、 回復可能な fatal error にはならず、 Error 例外をスローするようになりました。 同様に、Transliterator を clone すると、 内部の transliterator の複製に失敗した時に 致命的なエラーにならず、 Error 例外をスローするようになりました。
LDAP 拡張モジュールでは、 ldap_batch_modify() 関数に不明な変更タイプを渡すと、 致命的なエラーにならず、 Error 例外をスローするようになりました。