下位互換性のない変更点
PHP コア
配列でない値を配列スタイルでアクセスした場合
null, bool,
int, float または resource
型を ($null["key"]
のように)
配列としてアクセスしようとすると、警告が生成されるようになりました。
get_declared_classes() 関数
get_declared_classes() 関数は、まだインスタンス化されていない無名クラスを返さなくなりました。
fn
キーワード
fn
は、予約語になりました。特に、関数名やクラス名として使うことはできなくなりました。メソッド名やクラスの定数名の場合は使用できます。
ファイルの最後の <?php
タグ
ファイルの最後の (改行が最後に付かない) <?php
タグは、PHPタグの開始タグとして解釈されるようになりました。以前は、短い形式の開始タグ <?
の後にリテラル
php
を続けたものとして解釈されるか、(short_open_tag=1
の場合は) 文法エラー になるか、(short_open_tag=0
の場合は) <?php
というリテラルとして解釈されていました。
ストリームラッパー
ストリーム上で include/require
を使う場合、streamWrapper::stream_set_option() が
STREAM_OPTION_READ_BUFFER
オプション付きで呼び出されるようになります。カスタムのストリームラッパーの実装は
警告を回避するために streamWrapper::stream_set_option()
を実装する必要があるかもしれません (不十分な実装に対しては常に false
を返します)
シリアル化
シリアル化フォーマット o
は削除されました。
PHP
によって生成されなくなるので、手動で組まれた文字列のシリアル化を復元する場合のみ、壊れる場合があります。
パスワードアルゴリズムの定数
パスワードハッシュのアルゴリズムの識別子は、数値型ではなく、nullable な文字列型になりました。
-
PASSWORD_DEFAULT
は int型の 1 でしたが、 string の '2y' になりました。 (PHP 7.4.0, 7.4.1, 7.4.2 ではnull
でした) -
PASSWORD_BCRYPT
は int型の 1 でしたが、string の '2y' になりました。 -
PASSWORD_ARGON2I
は int型の 2 でしたが、string の 'argon2i' になりました。 -
PASSWORD_ARGON2ID
は int型の 3 でしたが、string の 'argon2id' になりました。
PASSWORD_DEFAULT, PASSWORD_BCRYPT, PASSWORD_ARGON2I, および PASSWORD_ARGON2ID 定数を正しく使っているアプリケーションは、正しく動作し続けるはずです。
htmlentities() 関数
htmlentities() 関数は 基本的なエンティティ置換だけをサポートしているエンコーディングで使われた場合、 (E_STRICT ではなく) E_NOTICE を発生させるようになりました。E_NOTICE が発生するのは、htmlspecialchars() の場合と同等です。
BCMath
BCMath 関数は、"32foo"
のような不完全な数値が渡された場合に警告を生成するようになりました。以前はそうした引数は0として解釈されていました。
CURL
CURLFile をシリアル化しようとすると、例外が発生するようになりました。以前は、シリアル化を復元しようとした場合のみ、例外が発生していました。
CURLPIPE_HTTP1
は非推奨になり、cURL 7.62.0
からサポートされなくなりました。
curl_version() 関数の $version
引数は推奨されません。デフォルトの
CURLVERSION_NOW
以外の値が渡された場合、警告が生成され、渡された引数は無視されます。
日付と時刻
DateTime や DateTimeImmutable のインスタンスに対して var_dump() 類似の関数を呼び出しても、オブジェクトでアクセス可能なプロパティのみを表示するようになりました。
DateInterval オブジェクトを (
==
, <
などを使って)
比較した場合、警告が出て常に false
が返されるようになりました。以前は、プロパティがない場合、全ての
DateInterval
オブジェクトが等しいと見做されていました。
国際化関数
idn_to_ascii() と idn_to_utf8()
関数のデフォルト値は、非推奨の INTL_IDNA_VARIANT_2003
ではなく INTL_IDNA_VARIANT_UTS46
となりました。
MySQLi
組み込みサーバーの機能は削除されました。少なくとも PHP 7.0 以降、この機能は壊れていました。
ドキュメントに書かれていない mysqli::$stat
プロパティは削除され、mysqli::stat()
に置き換えられました。
OpenSSL
openssl_random_pseudo_bytes()
関数は、エラーが発生した場合に例外をスローするようになりました。random_bytes()
関数も同じです。
特に、リクエストされたバイト数が0以下の場合には、
Error
がスローされ、十分なランダム性が得られなかった場合は
Exception が生成されます。
$crypto_strong
の出力引数は、
例外がスローされなかった場合は常に true
であることが保証されるので、明示的なチェックは不要です。
Regular Expressions (Perl互換)
PREG_UNMATCHED_AS_NULL
モードが使われた場合、後に続くマッチしなかったキャプチャグループにも null
(offset キャプチャが有効になっていた場合は
[null, -1]
になります) が設定されるようになりました。
これは、$matches
のサイズが常に同じになることを意味します。
PDO
PDO や PDOStatement のインスタンスをシリアル化しようとすると、PDOException ではなく Exception が生成されるようになりました。これは、シリアル化をサポートしていない他の内部的なクラスと一貫した挙動です。
ReflectionClassConstant, ReflectionMethod, ReflectionProperty のクラス定数の値が変更されました。
リフレクション
リフレクションオブジェクトをシリアル化しようとすると、例外を生成するようになりました。リフレクションオブジェクトのシリアル化はこれまでサポートされたことはなく、壊れたリフレクションオブジェクトを返していました。このバージョンから、明示的に禁止されました。
Standard PHP Library (SPL)
ArrayObject インスタンスに対して
get_object_vars()
関数を呼ぶと、ArrayObject
そのもの(またはそのサブクラス)
のプロパティを常に返すようになりました。以前は、ArrayObject::STD_PROP_LIST
フラグが指定されない限り、ラップされた 配列/オブジェクト
の値を返していました。
他に影響を受ける操作として、以下が挙げられます:
- ReflectionObject::getProperties()
- reset(), current() など。 Iterator メソッドを代わりに使ってください。
- オブジェクトのプロパティをリストとして扱うその他の操作も、影響を受ける可能性があります。 たとえば array_walk() 関数が挙げられます。
(array)
キャストは影響を受けません。この操作は引き続き、ラップされた配列を返すか、ArrayObject
のプロパティを返します。これは、ArrayObject::STD_PROP_LIST
フラグが指定されたかどうかによって異なります。
SplPriorityQueue::setExtractFlags() は、0を渡された場合に例外をスローするようになりました。以前は、次の配列を展開する操作の際に回復可能な致命的なエラーを生成していました。
ArrayObject, ArrayIterator,
SplDoublyLinkedList および
SplObjectStorage
は、Serializable に加えて、新たに
__serialize()
と __unserialize()
機構をサポートしました。
これによって、古いPHPバージョンでシリアル化されたペイロードはまだ復元可能であることを意味しますが、PHP
7.4
で生成された新しいペイロードを、古いバージョンは理解しないことを意味します。
Tokenizer
token_get_all()
関数は、トークンストリームに穴を開けるのではなく、T_BAD_CHARACTER
トークンを生成するようになりました。
外部から入力されるCookie
PHP 7.4.11 以降は、セキュリティ上の理由により、 外部から入力される Cookie の 名前 はurlデコードされなくなりました。
User Contributed Notes 1 note
Re: "The o serialization format has been removed. As it is never produced by PHP, this may only break unserialization of manually crafted strings."
This little-o serialisation format was used by PHP3 but was never generated by PH PHP4 or above. The deserialization code still recognised it, though, for reasons of backwards-compatibility with PHP3.
However, based on a bit of investigation, it looks like this code has been broken for about 15 years, so although this is listed as a deprecation, in practice it wasn't.
See this Stack Overflow question for a really great answer, with a lot more detail about this: https://stackoverflow.com/questions/65289729/what-was-phps-o-serialization-format-for