これまでのバージョンでは、ユーザー定義の関数に渡す引数が足りない場合は 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', ...)
のような形式)
が使えなくなりました。対象になるのは、別のスコープを調べたり変更したり、
あいまいな挙動になってしまったりするような関数です。
この変更の影響を受ける関数は、以下のとおりです。
<?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_srand()
のオプションの第二引数に MT_RAND_PHP
を指定すると、これまでの挙動 (間違った実装) を維持できます。
rand() と srand() は、それぞれ mt_rand() と mt_srand() のエイリアスになりました。つまり、 rand()、shuffle()、 str_shuffle()、array_rand() の出力がこれまでのバージョンとは変わるということです。
ASCII 制御文字 delete (0x7F
) は、
クォートしない限りは識別子として使えなくなりました。
error_log
に syslog
を指定した場合の変更
INI 項目 error_log
の設定値を
syslog
にした場合に、PHP のエラーレベルが syslog
のエラーレベルにマッピングされるようになりました。
これまでのバージョンではすべてのエラーが notice レベルで記録されていましたが、
この変更によって、今までよりも細やかな区別ができるようになります。
オブジェクトのコンストラクタの実行中に例外がスローされた場合に、 そのオブジェクトのデストラクタが呼ばれることはなくなりました。 以前のバージョンでは、場合によっては (例: そのオブジェクトが例外バックトレースなどで外部から参照される場合) デストラクタが呼ばれることもありました。
引数を参照渡しで受け取る関数を 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 項目は、削除されました。
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 エラーのエラーメッセージが、 "Catchable fatal error" から "Recoverable fatal error" に変更されました。
unserialize() 関数の $options パラメータの
allowed_classes
要素が、
型を厳密に解釈するようになりました。
つまり、array または bool
以外のあらゆる値が与えられても、
unserialize() は false
を返し、
E_WARNING
レベルの警告が発生します。
DateTime と DateTimeImmutable
は、現在時刻、明示的な時刻、
または相対時刻を示す文字列
(例: "first day of next month"
)
から構築されると、
マイクロ秒を適切に含めるようになりました。
これは、新しく生成されたふたつのインスタンスが、true
ではなくて
false
を返しやすくなったということです。
<?php
new DateTime() == new DateTime();
?>
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 例外を投げるようになりました。
mbstring 拡張機能では、 mb_ereg() 関数と mb_eregi() 関数が、 'e' オプションを使い、かつ 不正な PHP の式が渡された場合に ParseError 例外を投げるようになりました。
Mcrypt 拡張機能では、 mcrypt_encrypt() と mcrypt_decrypt() 関数が mcrypt を初期化できなかった場合に 致命的なエラーにならず、 Error 例外を投げるようになりました。
mysqli 拡張機能では、 不正なプロパティを読み出そうとしたり、 読み取り専用のプロパティに書き込もうとしたりすると、 致命的なエラーにならず、 Error 例外を投げるようになりました。
Reflection 拡張機能では、 リフレクションオブジェクトを取得できなかったり、 オブジェクトのプロパティを取得できなかったりすると、 致命的なエラーにならず、 Error 例外を投げるようになりました。
Session 拡張機能では、 セッションIDに文字列を返さないカスタムのセッションハンドラは、 セッションIDを生成しなければならない関数を呼んだ際に 致命的なエラーにならず、 Error 例外を投げるようになりました。
SimpleXML 拡張機能では、 名前が付いていない、または 重複した属性を作ろうとすると、 致命的なエラーにならず、 Error 例外を投げるようになりました。
SPL 拡張機能では、 SplDirectory オブジェクトを clone しようとすると、 致命的なエラーにならず、 Error 例外を投げるようになりました。 同じように、オブジェクトを繰り返している時に ArrayIterator::append() を呼び出すと、 Error 例外を投げるようになりました。
standard 拡張機能では、 assert()関数 の 最初のパラメーターに string 型の引数が与えられた場合、 かつ PHP のコードが不正だった場合に キャッチ可能な致命的なエラーではなく、 ParseError 例外を投げるようになりました。 同じように、 クラススコープの外側から forward_static_call() を呼び出すと、 Error 例外を投げるようになりました。
Tidy 拡張機能では、 tidyNode を手動で作ろうとすると、 致命的なエラーにならず、 Error 例外を投げるようになりました。
WDDX 拡張機能では、 シリアライズする時に循環参照が存在すると、 致命的なエラーにならず、 Error 例外を投げるようになりました。
XML-RPC 拡張機能では、 シリアライズする時に循環参照が存在すると、 致命的なエラーにならず、 Error 例外を投げるようになりました。
Zip 拡張機能では、 glob サポートが利用できない場合、 ZipArchive::addGlob() メソッドは 致命的なエラーにならず、 Error 例外を投げるようになりました。
use
経由で クロージャ
に束縛された変数名には、スーパーグローバル や
$this またはあらゆるパラメータ と同じ名前が使えなくなりました。
たとえば、次のような関数定義はすべて致命的なエラーが発生します。
<?php
$f = function () use ($_SERVER) {};
$f = function () use ($this) {};
$f = function ($param) use ($param) {};
long2ip() 関数は、 引数に string ではなく int を期待するようになりました。
serialize_precision
ini 設定が、
double 型の値をエンコードするときに、
シリアル化の精度を制御するようになりました。
空のキーをデコードすると、
プロパティ名が _empty_
ではなく、空のプロパティ名になります。
<?php
var_dump(json_decode(json_encode(['' => 1])));
上の例の出力は、 たとえば以下のようになります。
object(stdClass)#1 (1) { [""]=> int(1) }
json_encode() 関数に
JSON_UNESCAPED_UNICODE
フラグを渡すと、
U+2028 および U+2029 がエスケープされるようになりました。
mb_ereg() 関数 と
mb_eregi() 関数
の第3引数 (regs
) は、
マッチするものがなかった場合、空の配列が設定されるようになりました。
これより前のバージョンでは、このパラメータは変更されませんでした。
sslv2 ストリーム が OpenSSL から削除されました。
戻り値の型を宣言している関数内で、引数がないreturn文を使うと、
(戻り値の型を void と宣言していない場合)
E_COMPILE_ERROR
が発生するようになりました。
これは、そのreturn文に到達しない場合であっても同じです。