PHP8.5 / PHP8.4 / PHP8.3 / PHP8.2 / PHP8.1
2025/11/20にPHP8.5がリリースされました。
めでたいですね。
大きな新機能については、PHP8.0以降公開されるようになったランディングページで見ることができます。
PHP8.5ではデザインが一新されてすっきりクールになりました。
またマイグレーションガイドも存在します。
採用されたRFCについてはPHP8.5の新機能でまとめています。
ここでは、概要だけではなくUPGRADINGに載っている全ての変更点を全部見て回ることにします。
Backward Incompatible Changes
互換性のない変更点。
Core
It is no longer possible to use "array" and "callable" as class alias names in class_alias()
関数class_aliasで、エイリアス名としてarray・callableを使えなくなりました。
むしろ今まで使えてたのかよ。
Loosely comparing uncomparable objects to booleans was previously inconsistent
比較不可能なオブジェクトをbool型と比較した場合、これまで一貫性がなかったので揃えました。
$object = curl_init();
$true = true;
// PHP8.4
$object == true; // true (bool)$objectになる
$object == $true; // false 常にfalse
// PHP8.5
$object == true; // true (bool)$object
$object == $true; // true (bool)$object
The return value of gc_collect_cycles() no longer includes strings and resources that were indirectly collected through cycles.
関数gc_collect_cyclesの返り値に、文字列型とリソース型の数が含まれなくなりました。
ということらしいけどよくわからない。
It is now allowed to substitute static with self or the concrete class name in final subclasses.
finalサブクラスでstaticをselfで置き換えることができるようになりました。
final class TEST extends stdClass{
public static $a = 1;
public function __construct() {
echo static::$a; // 1
echo self::$a; // 1
echo TEST::$a; // 1
}
}
$a = new TEST();
とあるんだけどPHP8.4でも普通に動くのでよくわかりません。
なんか勘違いしてる?
The tick handlers are now deactivated after all shutdown functions, destructors have run and the output handlers have been cleaned up
tickハンドラは、シャットダウン関数やデストラクタなどが終わったあとは非アクティブになります。
シャットダウン中にregister_tick_functionするとバグる問題の対策です。
Traits are now bound before the parent class
parentクラスより先にtraitがバインドされるようになりました。
相当ややこしいことをしないと発生しないバグへの対策によるものです。
Errors emitted during compilation and class linking are now always delayed and handled after compilation or class linking
コンパイル中にエラーが発生しても、コンパイル終了まで待ってからエラーを発生させるようになりました。
ただし致命的エラーは即時発生して、ユーザ定義のエラーハンドラを無視します。
どんなときに異なる動作になるのかはよくわかりません。
Exceptions thrown by user-defined error handlers when handling class linking errors are not promoted to fatal errors anymore and do not prevent linking
ユーザ定義のクラスリンクエラーは致命的エラーではなくなりました。
とあるんだけどクラスリンクエラーいまいちわからない。
Applying #[\Attribute] to an abstract class, enum, interface, or trait triggers an error during compilation
抽象クラスやENUM、インターフェイス等にアトリビュート#[\Attribute]を書くとコンパイルエラーになります。
#[\Attribute]
interface TEST{}
// PHP8.5 Fatal error: Cannot apply #[\Attribute] to interface
// PHP8.4 エラー出ない
これまでは書いただけではエラーは起こらず、ReflectionAttribute::newInstanceしたときに初めて実行時エラーになっていました。
The disable_classes INI setting has been removed
ini設定disable_classesが削除されました。
これは特定のクラスだけを使用不可能にするという設定ですが、たとえばPDOを無効化するとPDO_MYSQLは存在するのに動かなかったりと異常な状態になってしまい問題が起きていました。
今後は、機能の無効化はエクステンション単位で行うことになります。
Destructing non-array values (other than NULL) using [] or list() now emits a warning
プリミティブ値をlistしようとしたらE_WARNINGが発生します。
$array = 1;
[$v1, $v2] = $array;
var_dump($v1, $v2); // $v1 = null, $v2 = null
// PHP8.5 PHP Warning: Cannot use int as array
// PHP8.4 エラー出ない
今まで出ていなかったのが謎ですね。
A warning is now emitted when casting floats to int if they cannot be represented as one
(int)キャストで値が壊れる場合にE_WARNINGが発生します。
var_dump((int)(PHP_INT_MAX+1)); // -9223372036854775808
// PHP8.5 Warning: The float 9.223372036854776E+18 is not representable as an int
// PHP8.4 エラー出ない
var_dump((int)1.5); // こっちはエラー出ない
値が壊れるというのはintの最大値最小値を超える操作のことであり、(int)1.5のような普通の丸めにおいてはエラーは出ません。
元々バグっていた計算だけにエラーが出ることになります。
A warning is now emitted when casting NAN to other types
NANを別の型に変換しようとするとE_WARNINGが発生します。
var_dump((string)NAN); // "NAN"
// PHP8.5 Warning: unexpected NAN value was coerced to string
// PHP8.4 エラー出ない
NANは存在している時点で異常である可能性が高いので、キャストではなくロジックでどうにかしましょう。
BZ2
bzcompress() now throws a ValueError when $block_size is not between 1 and 9.
bzcompressの第二引数$block_sizeが、1-9以外の場合にValueErrorが出るようになりました。
bzcompress() now throws a ValueError when $work_factor is not between 0 and 250.
bzcompressの第三引数$work_factorが、0-250以外の場合にValueErrorが出るようになりました。
DOM
Cloning a DOMNamedNodeMap, DOMNodeList, Dom\NamedNodeMap, Dom\NodeList, Dom\HTMLCollection, and Dom\DtdNamedNodeMap now fails.
DOMNamedNodeMapなどをcloneしようとしたら致命的エラーになります。
$a = new DOMNamedNodeMap();
$b = clone $a;
// PHP8.5 Fatal error: Uncaught Error: Trying to clone an uncloneable object
// PHP8.4 エラー出ない
そもそも、これまでもcloneしたDOMオブジェクトは正常に動作していなかったそうです。
FileInfo
finfo_file() and finfo::file() now throws a ValueError instead of a TypeError when $filename contains nul bytes
finfo_fileは、引数$filenameにヌルバイトが入っていた際に、これまでTypeErrorが発生していたところValueErrorが発生するようになりました。
finfo_file(finfo_open(FILEINFO_NONE), "a\0a");
// PHP8.5 Fatal error: Uncaught ValueError: finfo_file(): Argument #2 ($filename) must not contain any null bytes
// PHP8.4 Fatal error: Uncaught TypeError: finfo_file(): Argument #2 ($filename) must not contain any null bytes
本来ValueErrorが正しかったので修正されたとのことです。
Intl
The extension now requires at least ICU 57.1.
ICUバージョン57.1以上が必須になりました。
Windowsなら勝手に入ってるので気にする必要はなさそう。
The behaviour of Collator::SORT_REGULAR with respect to handling numeric strings is now aligned
Collator::SORT_REGULARの動作が修正されました。
$arr = [
'2023-02-04',
'2023-01-08',
'2021-01-03',
];
$coll = Collator::create('ja');
$coll->asort($arr, Collator::SORT_REGULAR);
var_dump($arr);
// PHP8.5 [2=>'2021-01-03', 1=>'2023-01-08', 0=>'2023-02-04']
// PHP8.4 [2=>'2021-01-03', 0=>'2023-02-04', 1=>'2023-01-08']
PHP8.4までは謎過ぎるソート順になっていました。
今後はSORT_REGULARと同じ動作になります。
LDAP
ldap_get_option() and ldap_set_option() now throw a ValueError when passing an invalid option
ldap_get_option・ldap_set_optionの引数$optionに正しくない値を与えるとValueErrorが発生するようになりました。
MBstring
Unicode data tables have been updated to Unicode 17.0
Unicodeのバージョンが17.0になりました。
17.0は2025年9月にリリースされたばかりの最新版です。
MySQLi
Calling the mysqli constructor on an already-constructed object is now no longer possible and throws an Error.
既に接続されているオブジェクトに対して、mysqliコンストラクタを呼び出すことができなくなりました。
よくわからんのだが複数の接続ができなくなったということ?
ODBC
ODBC now assumes that at least ODBC 3.5 functionality is available.
ODBCは、接続先が少なくともODBC 3.5をサポートしていることが前提になりました。
ODBC no longer has build flags to build against specific drivers
特定のドライバに対応するためのビルドフラグが削除されました。
Windows以外はiODBCやunixODBCを使えということだそうです。
そもそもODBCを使ったことがないからなんなのかよくわからない。
Opcache
The Opcache extension is now always built into the PHP binary and is always loaded.
Opcacheエクステンションは常にロードされ、削除できなくなりました。
PHP本体からOpcacheを使っている部分が多いため、PHPコアと同じ扱いにされます。
ini設定opcache.enableでユーザから使えないようにすることは、これまでどおりに可能です。
PCNTL
pcntl_exec() now throws ValueErrors when entries of the $args parameter contain null bytes.
pcntl_execの第二引数$argsにヌルバイトが入っている場合ValueErrorが出るようになりました。
pcntl_exec() now throws ValueErrors when entries or keys of the $env_vars parameter contain null bytes.
pcntl_execの第三引数$env_varsにヌルバイトが入っている場合ValueErrorが出るようになりました。
PCRE
The extension is compiled without semi-deprecated PCRE2_EXTRA_ALLOW_LOOKAROUND_BSK compile option.
PCREのコンパイルオプションからフラグPCRE2_EXTRA_ALLOW_LOOKAROUND_BSKが削除されました。
preg_match('~a(?=\Kb)~', 'abc', $matches);
var_dump($matches); // [0=>""]
// PHP8.5 Warning: preg_match(): Compilation failed: \K is not allowed in lookarounds
// PHP8.4 エラー出ない
これは正規表現メタ文字\Kの使用に関するフラグのようですが、\Kの情報が全然出てこないのでよくわからんな。
マッチングには全文を用いつつキャプチャ範囲は\Kより後にするという先読みアサーションと似たような機能ですが、先読みアサーションと\Kを同時に使うとおかしくなるのでPCREでは同時使用を禁止した、ただし後方互換のため許可するオプションPCRE2_EXTRA_ALLOW_LOOKAROUND_BSKを残しておいたんだけどやっぱり動きがおかしかったので使うのを辞めてくれとPCREから要請が来た、というかんじのようです。
なにがなんだか。
PDO
The constructor arguments set in conjunction with PDO::FETCH_CLASS now follow the usual CUFA (call_user_func_array) semantics.
PDO::FETCH_CLASSの動作がcall_user_func_arrayと同じようになりました。
未確認ですが、たぶんコンストラクタより先にプロパティがセットされるみたいな変な挙動をどうにかしたものだと思います。
Attempting to call PDOStatement::setFetchMode during a call to PDO::fetch(), PDO::fetchObject(), PDO::fetchAll() will now throw an Error.
PDOStatement::fetchなどの引数の中でPDOStatement::setFetchModeを呼び出そうとするとエラーになります。
小細工をせず普通に使えということみたい。
The value of the constants PDO::FETCH_GROUP, PDO::FETCH_UNIQUE, PDO::FETCH_CLASSTYPE, PDO::FETCH_PROPS_LATE, and PDO::FETCH_SERIALIZE have changed.
PDO定数の値が変更されました。
var_dump(PDO::FETCH_GROUP);
// PHP8.5 32
// PHP8.4 65536
きちんと定数で使っているかぎり影響はありません。
A ValueError is now thrown if PDO::FETCH_PROPS_LATE is used with a fetch mode different than PDO::FETCH_CLASS
PDO::FETCH_CLASS以外のフェッチモードでPDO::FETCH_PROPS_LATEを使うとValueErrorが出るようになりました。
A ValueError is now thrown if PDO::FETCH_INTO is used as a fetch mode in PDO::fetchAll()
フェッチモードPDO::FETCH_INTOでPDOStatement::fetchAllを使うとValueErrorが出るようになりました。
PDO_FIREBIRD
A ValueError is now thrown when trying to set a cursor name that is too long on a PDOStatement
カーソル名に長すぎる名を付けようとするとValueErrorが発生するようになりました。
具体的に何文字かは不明。
Session
Attempting to write session data where $_SESSION has a key containing the pipe character will now emit a warning instead of silently failing.
セッション変数のキーに|を使うと、これまでは黙って失敗していたのがE_WARNINGを出すようになりました。
$_SESSION['a|b'] = 1; // 実は保存されない
// PHP8.5 E_WARNING
// PHP8.4 エラー出ない
手元で試したところ、値が保存されないどころか$_SESSION自体が消滅したのだがこれは想定された動作なのだろうか?
SimpleXML
Passing an XPath expression that returns something other than a node set to SimpleXMLElement::xpath() will now emit a warning and return false
SimpleXMLElement::xpathにノード以外を返すXPathを渡すと、E_WARNINGを出すようになりました。
とあるのですが、具体的にノード以外のXPathをどう作るのかわからない。
SPL
ArrayObject no longer accepts enums
ArrayObjectにENUMを渡せなくなりました。
とあるのですが、なんか普通に動いたのでよくわかりません。
enum Suit{
case Hearts;
case Diamonds;
case Clubs;
case Spades;
}
$arr = new ArrayObject(Suit::cases()); // 動く???
SplFileObject::fwrite's parameter $length is now nullable.
SplFileObject::fwriteの第二引数$lengthの型がintからint|nullになり、デフォルト値が0からnullになりました。
たぶん0を渡すとこれまで無制限だったのが、何も書きこまないってなると思います。
Standard
Using a printf-family function with a formatter that did not specify the precision previously incorrectly reset the precision
printfのフォーマットで精度を指定しなかった場合、0桁になります。
printf("%.f\n", 3.1415926535);
// PHP8.5 3
// PHP8.4 3.141593
ドキュメントでは0 is assumedとなっており、本来なら小数点以下0桁であるべきだったところがなっていなかったというバグです。
SOAP
SoapClient::__doRequest() expects a new, optional $uriParserClass parameter
SoapClient::__doRequestに引数$uriParserClassが必須になります。
New Features
新機能。
Core
Closure is now a proper subtype of callable
Closureはcallableの適切なサブタイプになりました。
var_dump(is_a('Closure', 'callable')); // false
とあるのだけど確認方法がわかりません。
元々callableな引数にClosureを渡すことはできていたし、callableはクラスでないのでinstanceofなどで調べることもできません。
Added support for Closures and first class callables in constant expressions
定数式でクロージャが使えるようになります。
const A = static function() {
echo 'Hello, World!';
};
var_dump(A);
// PHP8.5 object(Closure)
// PHP8.4 PHP Fatal error: Constant expression contains invalid operations
ただこれ確かにAはClosureオブジェクトになるんですが、普通にA()と呼び出すことができませんでした。
constant('A')();ってやると実行できるんですがこれで正しいのか?
Fatal Errors (such as an exceeded maximum execution time) now include a backtrace
致命的エラーメッセージにバックトレースが標準装備されます。
<?php
function a() {
return b();
}
function b() {
return a();
}
a();
/* PHP8.5
PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
#1 path/to/sample.php(7): a()
#2 path/to/sample.php(3): b()
#3 path/to/sample.php(7): a()
#4 path/to/sample.php(3): b()
#5 path/to/sample.php(7): a()
#6 path/to/sample.php(3): b()
…
*/
PHP8.4まではバックトレースはありませんでした。
調査解析が楽になりますね。
Added the #[\NoDiscard] attribute to indicate that a function's return value is important and should be consumed.
返り値を無視することを許さないNoDiscardアトリビュートが追加されました。
#[\NoDiscard]
function hoge(): int{return 1;}
hoge();
// PHP8.5 PHP Warning: The return value of function hoge() should either be used or intentionally ignored by casting it as (void)
// PHP8.4 エラー出ない
必ず$ret = hoge();のような形で受け取る必要があります。
受け取った上で使わないのは問題ありません。
このアトリビュートは、fopenのような普通の関数には使用するべきではなく、flockのように返り値を無視すると致命的な問題が発生する可能性のあるものに使います。
PHP本体ではflockとDateTimeImmutable::set*()だけに搭載されます。
Added the (void) cast to indicate that not using a value is intentional.
(void)キャストが追加されました。
#[\NoDiscard]
function hoge(): int{return 1;}
(void)hoge();
// PHP8.5 エラー出ない
// PHP8.4 PHP Parse error: syntax error
NoDiscardアトリビュートにおいて、返り値を使わないことを明示します。
ただ普通に返り値を受け取った方が安全だと思います。
Added asymmetric visibility support for static properties.
静的プロパティの非対称可視性に対応しました。
class Example
{
public private(set) static string $classTitle = '読めるけど書けない';
}
var_dump(Example::$classTitle); // '読めるけど書けない'
Example::$classTitle = '書けない'; // エラー
書き込みはprivateで読み取りはpublicな静的プロパティをさくっと作れます。
便利ですね。
Added support for casts in constant expressions.
定数式でキャストできるようになりました。
const A = (string)1;
// PHP8.5 エラー出ない
// PHP8.4 PHP Fatal error: Constant expression contains invalid operations
Added support for attributes on compile-time non-class constants.
定数にアトリビュートが書けるようになりました。
The #[\Deprecated] attribute can now be used on constants.
定数に#[\Deprecated]アトリビュートが書けるようになりました。
#[\Deprecated]
const A = 1;
var_dump(A); // PHP Deprecated: Constant A is deprecated
どんどんDeprecateしていきましょう。
Added the pipe (|>) operator.
パイプライン演算子です。
$result = "Hello World"
|> htmlentities(...)
|> str_split(...)
|> (fn($x) => array_map(strtoupper(...), $x))
|> (fn($x) => array_filter($x, fn($v) => $v != 'O'))
;
var_dump($result); // ["H", "E", "L", "L", " ", "W", "R", "L", "D"]
普通に書くと中間変数をたくさん書かないといけない、一文にすると括弧だらけなうえ逆順になって分かりにくくなる、という関数の連鎖が、非常に分かりやすく実行順に書けるようになります。
Constructor property promotion can now be used for final properties.
コンストラクタ引数昇格にfinalプロパティが書けるようになりました。
class HOGE{
public function __construct(
final public int $x
){}
}
var_dump(new HOGE(1)); // HOGE::$x=1が生える
コンストラクタ引数昇格はPHP8.0で、finalプロパティはPHP8.4で書けるようになりました。
しかしPHP8.4ではfinalプロパティのコンストラクタ引数昇格ができなかったので、対応したものとなります。
対応忘れていただけなのでは?という気がしないでもないですが、実際はPHP8.4時点では意図的に非対応にしていたそうです。
#[\Override] can now be applied to properties.
アトリビュート#[\Override]をプロパティにも書けるようになりました。
class FOO{
public string $name = 'FOO';
}
class BAR extends FOO{
#[\Override]
public string $name = 'BAR';
}
Overrideを明示できるので、ソースコードが読みやすくなるでしょう。
親クラスに定義のないプロパティをOverrideした場合は、もちろんエラーになります。
The #[\DelayedTargetValidation] attribute can be used to suppress compile-time errors
コンパイルエラーを実行時エラーまで遅延させるアトリビュート#[\DelayedTargetValidation]が追加されました。
#[\DelayedTargetValidation]
#[\Attribute]
enum Suit{
case HEARTS;
case DIAMONDS;
case CLUBS;
case SPADES;
}
var_dump(Suit::DIAMONDS);
#[\DelayedTargetValidation]がない場合は、ENUMに#[\Attribute]を書いた罪でコンパイルエラーになります。
#[\DelayedTargetValidation]をつけると、実行時までエラーが遅延され……エラーが出ずに正常終了したんだけどなんで?
Curl
Added support for share handles that are persisted across multiple PHP requests
リクエストを越えてcurlハンドルを維持する関数curl_share_init_persistentが追加されました。
$cs = curl_share_init_persistent([CURL_LOCK_DATA_CONNECT, CURL_LOCK_DATA_SSL_SESSION, CURL_LOCK_DATA_DNS]);
$ch = curl_init("https://localhost");
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_SHARE, $cs);
curl_exec($ch);
あんまり一般ユーザは使用しないほうがいい機能だと思われます。
Added support for CURLINFO_USED_PROXY, CURLINFO_HTTPAUTH_USED, and CURLINFO_PROXYAUTH_USED
curl_getinfoで取得できる値CURLINFO_USED_PROXY・CURLINFO_HTTPAUTH_USED・CURLINFO_PROXYAUTH_USEDが追加されました。
used_proxyはプロキシを使用したか、httpauth_used・proxyauth_usedは認証を使用したかのようです。
Curl定数は基本的にlibcurlに実装されたものをそのまま取り込んだものになります。
Added CURLOPT_INFILESIZE_LARGE Curl option
定数CURLOPT_INFILESIZE_LARGEが追加されました。
CURLOPT_INFILESIZEは64ビットシステムだろうが32ビット符号付き整数しか受け付けないので、きちんとシステム上限を使ってくれるCURLOPT_INFILESIZE_LARGEに対応しました。
Added CURLFOLLOW_OBEYCODE, CURLFOLLOW_FIRSTONLY and CURLFOLLOW_ALL values for CURLOPT_FOLLOWLOCATION
CURLOPT_FOLLOWLOCATIONの設定値として使える定数CURLFOLLOW_OBEYCODE・CURLFOLLOW_FIRSTONLY・CURLFOLLOW_ALLが追加されました。
CURLOPT_FOLLOWLOCATIONはリダイレクトをどう扱うかの設定項目です。
CURLFOLLOW_OBEYCODEはリダイレクトを厳密に辿る、CURLFOLLOW_FIRSTONLYは最初の一回だけリダイレクトする、CURLFOLLOW_ALLはtrueと同じです。
Added support for CURLINFO_CONN_ID to the curl_getinfo() function
curl_getinfoで取得できる値CURLINFO_CONN_IDが追加されました。
Curl接続のコネクションIDを取得できます。
接続を再利用したいとかの場合に使えるらしいです。
Added support for CURLINFO_QUEUE_TIME_T (libcurl >= 8.6.0) to the curl_getinfo() function.
curl_getinfoで取得できる値CURLINFO_QUEUE_TIME_Tが追加されました。
libcurlが接続キューを受け取ってからリクエストを送信するまでにかかった時間を取得できるみたい?
Added support for CURLOPT_SSL_SIGNATURE_ALGORITHMS to specify the signature algorithms to use for TLS.
SSLの署名アルゴリズムを指定する定数CURLOPT_SSL_SIGNATURE_ALGORITHMSが追加されました。
curl_setopt($ch, CURLOPT_SSL_SIGNATURE_ALGORITHMS , 'DSA+SHA256:rsa_pss_pss_sha256');
のように使うみたい。
DOM
Added Dom\Element::$outerHTML.
Dom\Elementにプロパティ$outerHTMLが追加されました。
Added $children property to Dom\ParentNode implementations.
Dom\ParentNodeにプロパティ$childrenが追加されました。
このへん具体的になんなのかが書かれてないのでよくわかりません。
EXIF
Add OffsetTime* Exif tags.
EXIFのタグOffsetTime*が追加されました。
Added support for HEIF/HEIC.
HEIF・HEIC形式に対応しました。
Filter
Add new FILTER_THROW_ON_FAILURE flag which can be passed to the filter functions
定数FILTER_THROW_ON_FAILUREが追加されました。
filter_var('2', FILTER_VALIDATE_BOOL, FILTER_THROW_ON_FAILURE);
// Fatal error: Uncaught Filter\FilterFailedException: filter validation failed
フィルタ関数は失敗した場合は単にfalseを返しますが、FILTER_THROW_ON_FAILUREを渡すと検証失敗時にエラーが出るようになります。
Intl
Added class constants NumberFormatter::CURRENCY_ISO, NumberFormatter::CURRENCY_PLURAL, NumberFormatter::CASH_CURRENCY, and NumberFormatter::CURRENCY_STANDARD
NumberFormatterに定数が追加されました。
これはICUの実装に合わせたもの、だと思うのですがドキュメント等が見当たらなかったので具体的にどんな定義なのかはよくわかりません。
Added Locale::addLikelySubtags and Locale::minimizeSubtags to handle likely tags on a given locale.
LocaleにaddLikelySubtagsメソッドが追加されました。
Locale::addLikelySubtags('ja-JP'); // "ja_Jpan_JP"
不明なロケールから、最も似たような名前のロケールを返してくれるみたい。
ていうかja-JPって存在しないのね。
Added IntlListFormatter class to format, order, and punctuate a list of items with a given locale
IntlListFormatterクラスが追加されました。
ICU67で導入されたIntlフォーマット機能をサポートしたようです。
var_dump(new IntlListFormatter('ja-JP',IntlListFormatter::TYPE_AND)->format([1,2,3])); // "1、2、3"
var_dump(new IntlListFormatter('ja-JP',IntlListFormatter::TYPE_OR )->format([1,2,3])); // "1、2、または3"
var_dump(new IntlListFormatter('en-US',IntlListFormatter::TYPE_AND)->format([1,2,3])); // "1, 2, and 3"
var_dump(new IntlListFormatter('en-US',IntlListFormatter::TYPE_OR )->format([1,2,3])); // "1, 2, or 3"
うーん微妙。
PDO_Sqlite
Added class constant Pdo_Sqlite::ATTR_BUSY_STATEMENT.
定数Pdo\Sqlite::ATTR_BUSY_STATEMENTが追加されました。
たぶんクエリが実行中のロックを表すSQLITE_BUSYのことだと思いますが、なんにも書かれないのでよくわかりません。
Added class constants Pdo_Sqlite::ATTR_EXPLAIN_STATEMENT, Pdo_Sqlite::EXPLAIN_MODE_PREPARED, Pdo_Sqlite::EXPLAIN_MODE_EXPLAIN, Pdo_Sqlite::EXPLAIN_MODE_EXPLAIN_QUERY_PLAN.
各種定数が追加されました。
このあたりも詳細が書かれていませんが、名前からしておそらくEXPLAINが取得できるのではないでしょうか。
Added PDO\Sqlite::ATTR_TRANSACTION_MODE connection attribute
定数PDO\Sqlite::ATTR_TRANSACTION_MODEが追加されました。
設定できる値はPdo\Sqlite::TRANSACTION_MODE_DEFERRED・Pdo\Sqlite::TRANSACTION_MODE_IMMEDIATE・Pdo\Sqlite::TRANSACTION_MODE_EXCLUSIVEです。
PDO\SQLite::connectの引数に指定することで、トランザクションモードを設定可能です。
Session
session_set_cookie_params(), session_get_cookie_params(), and session_start() now support partitioned cookies
session_startなどの関数の引数オプションがキーpartitionedを受け付けます。
session_start(['secure' => true, 'partitioned' => true]);
これはCHIPSという仕組みへの対応で、PHPでpartitionedが発行できるようになります。
そもそも任意の引数を渡せるようにしてほしいんだけど
SOAP
Enumeration cases are now dumped in __getTypes().
SoapClient::__getTypesでxsd:enumerationが出力されるようになりました。
support for Soap 1.2 Reason Text xml:lang attribute.
Soap 1.2のxml:lang属性に対応しました。
これに伴い、SoapFault::__constructに引数$langが追加されました。
このあたりはSOAPの仕様に準拠していなかったので合わせたということです。
これで.NETのSOAPと完全互換することになります。
でもSOAPとかもう使わないよね。
Sqlite
Added class constants Sqlite3Stmt::EXPLAIN_MODE_PREPARED, Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN and Sqlite3Stmt::EXPLAIN_MODE_EXPLAIN_QUERY_PLAN.
SQLite3StmtにEXPLAINモードの定数が追加されました。
PDO\Sqlite::ATTR_TRANSACTION_MODEのやつと同じだと思います。
Standard
mail() now returns the actual sendmail error and detects if the sendmail process was terminated unexpectedly.
関数mailは、Sendmailがエラーを返してきたらE_WARNINGを出すようになりました。
実はmail関数はSendmailにデータを横流ししているだけです。
Sendmailがエラーを出したとしても、これまではエラーを完全に無視してfalseを返していたので、原因の特定が困難でした。
今後は原因がわかりやすくなります。
getimagesize() now supports HEIF/HEIC images.
関数getimagesizeがHEIF/HEIC形式に対応しました。
getimagesize() now supports SVG images when ext-libxml is also loaded.
関数getimagesizeがSVGに対応しました。
The array returned by getimagesize() now has two additional entries
関数getimagesizeの返り値にwidth_unit・height_unitが追加されました。
名前のとおり長さの単位で、pxやcm等になります。
setcookie() and setrawcookie() now support the "partitioned" key.
setcookieなどの関数の引数オプションがキーpartitionedを受け付けるようになりました。
XSL
The $namespace argument of XSLTProcessor::getParameter(), XSLTProcessor::setParameter() and XSLTProcessor::removeParameter() now actually works instead of being treated as empty.
XSLTProcessor::getParameterなどの引数$namespaceが機能するようになりました。
これまでは何を入れても空白扱いだったみたい。
Zlib
flock() is now supported on zlib streams.
Changes in SAPI modules
SAPIモジュールの変更点。
CLI
Trying to set a process title that is too long with cli_set_process_title() will now fail
関数cli_set_process_titleに超長いプロセス名を渡した場合、これまでは適当に切り詰められていたのが、普通に失敗するようになりました。
そもそもプロセス名を変更できることを初めて知ったわ。
Added a new --ini=diff option to print INI settings changed from the builtin default.
コマンドライン引数--ini=diffが追加されました。
php.iniのデフォルト値から変更されている項目だけを一覧できるという超便利機能です。
FPM
FPM with httpd ProxyPass optionally decodes the full script path.
ProxyPassディレクティブが有効な場合、スクリプトのファイル名がdecodeされます。
ini設定fastcgi.script_path_encodedで、そのdecodeを防ぐことができます。
とあるんだけど、このdecodeってのがどういう意味のdecodeなのかはよくわからない。
FPM access log limit now respects log_limit value.
FPMのアクセスログは、ini設定log_limitを守るようになりました。
これまで守ってなかったんかーい。
Deprecated Functionality
非推奨になった項目。
なお例では省略していますが、実際はエラーメッセージにuse shell_exec() insteadのように代替案が表示されており、移行が容易になっています。
Core
Trying to produce output within a user output handler is deprecated.
ユーザエンド出力ハンドラ内でのテキスト出力が非推奨になりました。
ob_start(function($string) {
echo $string;
return $string;
});
echo 'hoge';
ob_end_flush(); // PHP Deprecated:ob_end_flush(): Producing output from user output handler is deprecate
エラーはob_end_flushで出ますが、実際問題となるのはecho $string;です。
これは出力されることがないので意味がないうえ、デバッグも困難になるため禁止します。
Non-canonical cast names (boolean), (integer), (double), and (binary) have been deprecated
キャスト(boolean)・(integer)・(double)・(binary)が非推奨になりました。
(integer)1.1; // PHP Deprecated: Non-canonical cast (integer) is deprecated
(int)1.1; // エラー出ない
これらは大昔の型名が統一されていなかったころの名残であり、そろそろいいだろうということで削除されます。
今後は(bool)・(int)・(float)・(string)を使いましょう。
The $exclude_disabled parameter of the get_defined_functions() function has been deprecated
関数get_defined_functionsの引数$exclude_disabledが非推奨になりました。
PHP8.0で無効化した関数は存在しないものと扱われるようになったため、この引数があろうがなかろうが出力は変わらなくなっていました。
Terminating case statements with a semicolon instead of a colon has been deprecated.
case文の区切りに;を使うことが非推奨になりました。
$int = 1;
switch ($int) {
case 1:
echo '1';
break;
case 2; // PHP Deprecated: Case statements followed by a semicolon (;) are deprecated
echo '2';
break;
}
そもそもこんな文法初めて知ったわ。
The backtick operator as an alias for shell_exec() has been deprecated.
バックティック ` が非推奨になりました。
echo `date`; // Deprecated: The backtick (`) operator is deprecated
これがシステムコールだなんて目立たな過ぎて危ないですからね。
今後はshell_execを使いましょう。
Returning null from __debugInfo() has been deprecated.
マジックメソッド__debugInfoの返り値nullが非推奨になりました。
そもそもシグネチャは前からarrayでした。
今後は中身が不要な場合は[]を返しましょう。
The report_memleaks INI directive has been deprecated.
ini設定report_memleaksが非推奨になりました。
これはデバッグビルドにおいてメモリリークを通知してくれるという機能です。
そもそもメモリリークは修正されるべきPHP本体のバグであり、またproductionビルドにはまったく無関係な機能なので削除されます。
Constant redeclaration has been deprecated.
定数の再定義のエラーメッセージが変更されました。
const A = 1;
const A = 2;
// PHP8.5 PHP Warning: Constant A already defined, this will be an error in PHP 9
// PHP8.4 PHP Warning: Constant A already defined
E_WARNING自体は変わりませんが、PHP9でエラーになることが明記されました。
まあクラス定数の二重定義はエラーになるのに、こちらがエラーにならない理由もありませんからね。
meaning that incrementing non-numeric strings is now deprecated.
文字列のインクリメントが非推奨になりました。
$str = 'a';
$str++; //PHP Deprecated: Increment on non-numeric string is deprecated
$str = str_increment($str); // エラー出ない
PHP8.3で導入されたstr_incrementへ移行するための猶予期間でした。
今後は文字列インクリメントにはstr_incrementを使いましょう。
The following closure binding issues, which already emit an E_WARNING, are now deprecated
正しくない方法でクロージャをバインドすると非推奨が出るようになりました。
これまでも既にE_WARNINGが発生していたので、廃止が強調されます。
$c = static function() {};
Closure::bind($c, null, new stdClass()); // PHP Warning: Cannot bind closure to scope of internal class stdClass
手元の8.5.0ではE_WARNINGのままでした。
あれ?
Using null as an array offset or when calling array_key_exists() is now deprecated.
array_key_exists(null)が非推奨になりました。
$searchArray = [''=>1];
array_key_exists(null, $searchArray); // Deprecated: Using null as the key parameter for array_key_exists() is deprecated
array_key_exists(null)は何故かarray_key_exists('')と同じ動作になっていて、これはnullの通常の扱いとは異なります。
そのため、この使用方法は削除されます。
Deriving $_SERVER['argc'] and $_SERVER['argv'] from the query string for non-CLI SAPIs has been deprecated.
$_SERVER['argc']・$_SERVER['argv']が非推奨になりました。
これはCVE-2024-52301に関連するものだと思います。
ini設定register_argc_argvを設定するとコマンドライン引数を$_SERVER['argc']で取れるようになるのですが、実はこれHTTPリクエストからも設定可能です。
従って想定していない値を突っ込まれる可能性があるため、この機能を削除します。
コマンドライン引数は$argvから、HTTPリクエストは$_REQUESTから取得、と完全に分けることで安全性を高めましょう。
The __sleep() and __wakeup() magic methods have been soft-deprecated.
マジックメソッド__sleep・__wakeupが非推奨になりました。
マジックメソッド__serialize・__unserializeが完全上位互換なので、そちらを使いましょう。
Curl
The curl_close() function has been deprecated
関数curl_closeが非推奨になりました。
$curl = curl_init();
curl_close($curl); // Deprecated: Function curl_close() is deprecated since 8.5
curl_closeはPHP8.0以降何もしていませんでした。
そのため無意味なコードを削除します。
ではcurlハンドルはいつ閉じられるのかというと、ハンドルへの参照がなくなったときに自動的にクローズされます。
The curl_share_close() function has been deprecated
関数curl_share_closeが非推奨になりました。
こちらも同じ理由です。
Date
The DATE_RFC7231 and DateTimeInterface::RFC7231 constants have been deprecated.
定数DATE_RFC7231・DateTimeInterface::RFC7231が非推奨になりました。
$date = new \DateTime('2025/01/01 09:00:00', new DateTimeZone('Asia/Tokyo'));
$date->setTimeZone(new DateTimeZone('GMT'));
echo $date->format(DATE_RFC7231)."\n"; // Wed, 01 Jan 2025 00:00:00 GMT
$date->setTimeZone(new DateTimeZone('Asia/Tokyo'));
echo $date->format(DATE_RFC7231); // Wed, 01 Jan 2025 09:00:00 GMT
RFC 7231のフォーマットは<day-name>, <day> <month> <year> <hour>:<minute>:<second> GMTです。
出力フォーマットにGMTが含まれているので、タイムゾーンがどこだろうが常に出力はGMTの00:00:00になるべきなのですが、実際はタイムゾーンによって値が変わってしまっています。
バグではなく機能不足らしいのですがよくわかりません。
The __wakeup() magic method of DateTimeInterface, DateTime, DateTimeImmutable, DateTimeZone, DateInterval, and DatePeriod has been deprecated
メソッドDateTimeInterface::__wakeupが非推奨になりました。
わざわざ自力で呼んだりでもしないかぎり、自動的に__unserializeが使われるので特に気にする必要はないと思います。
FileInfo
The finfo_close() function has been deprecated.
関数finfo_closeが非推奨になりました。
curl_closeと全く同じ理由です。
The $context parameter of the finfo_buffer() function has been deprecated as it is ignored.
関数finfo_bufferの引数$contextが非推奨になりました。
この引数は元々無視されていました。
GD
関数imagedestroyが非推奨になりました。
curl_closeと全く同じ理由です。
Hash
The MHASH_* constants have been deprecated
mhash自体がPHP8.1で削除されたので、この定数は全く意味がありませんでした。
Intl
The intl.error_level INI setting has been deprecated.
ini設定intl.error_levelが非推奨になりました。
これはIntlで発生するエラーをE_ERRORやE_WARNINGなど任意に設定できる機能なのですが、内部処理的に困ったことになっていたらしいので削除されます。
今後はintl.use_exceptionsで例外を出すようにしましょう。
そもそもなんでこんな機能があったんだろう。
LDAP
Specific Oracle Instant Client calls and constants have been deprecated.
一部のOracle Instant Client呼び出しが非推奨になりました。
OracleのLDAP実装は対応していない機能があるのでOpenLDAPに移行する、そのため使えなくなる機能があるそうです。
LDAPとか使ったことないからさっぱりわからない。
MySQLi
The mysqli_execute() alias function has been deprecated.
関数mysqli_executeが非推奨になりました。
これはエイリアスであり、正しい関数名はmysqli_stmt_executeです。
mysqliオブジェクトではなくmysqli_stmtオブジェクトに使われるものであり、誤解を招く命名なので削除されます。
OpenSSL
The $key_length parameter for openssl_pkey_derive() has been deprecated.
関数openssl_pkey_deriveの引数$key_lengthが非推奨になりました。
下手に設定すると脆弱な暗号になってしまうため、設定できないほうが安全です。
PDO
The "uri:" DSN scheme has been deprecated due to security concerns with DSNs coming from remote URIs.
これは接続先をファイル名やURLで決められるという便利な機能ですが、想像通りDNSキャッシュポイズニング等で大変なことになるため削除されます。
Driver specific constants in the PDO class have been deprecated.
ドライバ固有の定数が、PDO直下からドライバに移動されます。
例としてPDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERTはPdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERTになります。
新しい定数自体はずっと前から用意されていて、今回は古いほうを削除する対応になります。
Deprecated: Constant PDO::MYSQL_ATTR_SSL_VERIFY_SERVER_CERT is deprecated since 8.5, use Pdo\Mysql::ATTR_SSL_VERIFY_SERVER_CERT insteadのように親切なメッセージが出るので、さくっと置換するだけで対応可能です。
Driver specific methods in the PDO class have been deprecated.
ドライバ固有のメソッドが、PDO直下からドライバに移動されます。
例としてPDO::pgsqlGetPid()はPdo\Pgsql::getPidになります。
対応方法も定数と同じです。
PDO_PGSQL
Constants related to transaction states have been deprecated
Pdo\Pgsql::TRANSACTION_IDLEなどPdo\Pgsqlのトランザクション定数が非推奨になりました。
PostgreSQLのトランザクション定数は有効ですが、Pdo\Pgsqlでは使われていないということです。
Reflection
The setAccessible() methods of various Reflection objects have been deprecated
setAccessibleが非推奨になりました。
PHP8.1以降、このメソッドは何もしていませんでした。
Calling ReflectionClass::getConstant() for constants that do not exist has been deprecated.
存在しないクラス定数に対するReflectionClass::getConstantが非推奨になりました。
class Demo {
public const EXISTS = false;
}
$r = new ReflectionClass( Demo::class );
var_dump( $r->getConstant( 'EXISTS' ) ); // false
var_dump( $r->getConstant( 'MISSING' ) ); // false
何故かというと、存在しない定数と、値がfalseの定数の区別がつかないからです。
ReflectionClass::hasConstantを使いましょう。
Calling ReflectionProperty::getDefaultValue() for properties without default values has been deprecated.
デフォルト値のないプロパティに対するReflectionProperty::getDefaultValueが非推奨になりました。
class Demo {
public $hasDefault = null;
public $noDefault;
}
$r1 = new ReflectionProperty( Demo::class, 'hasDefault' );
var_dump( $r1->getDefaultValue() ); // null
$r2 = new ReflectionProperty( Demo::class, 'noDefault' );
var_dump( $r2->getDefaultValue() ); // null
何故かというと、デフォルト値がない場合と、デフォルト値がnullの場合の区別がつかないからです。
ReflectionClass::hasDefaultValueを使いましょう。
SPL
Unregistering all autoloaders by passing the spl_autoload_call() function as a callback argument to spl_autoload_unregister() has been deprecated.
https://www.php.net/manual/ja/function.spl-autoload-unregister.phpの引数にspl_autoload_callを渡すことが非推奨になりました。
spl_autoload_unregister('spl_autoload_call'); // Deprecated: spl_autoload_unregister(): Using spl_autoload_call() as a callback for spl_autoload_unregister() is deprecated
// PHP8.5以降
foreach (spl_autoload_functions() as $fn) {
spl_autoload_unregister($fn);
}
どういうこと?
これまではこの謎の記法で登録されたオートローダを全削除できていたらしいです。
この動きはドキュメント化されておらず、動作的にも正しくないので削除されます。
まあ開発時か検証時にちょっと楽する裏技として入れていたものとかだったのでしょう。
The SplObjectStorage::contains(), SplObjectStorage::attach(), and SplObjectStorage::detach() methods have been deprecated
SplObjectStorage::contains・SplObjectStorage::attach・SplObjectStorage::detachが非推奨になりました。
現代の命名規則に沿っていません。
かわりにSplObjectStorage::offsetExists・SplObjectStorage::offsetSet・SplObjectStorage::offsetUnsetを使いましょう。
Using ArrayObject and ArrayIterator with objects has been deprecated.
ArrayObjectとArrayIteratorにオブジェクトを突っ込むことが非推奨になりました。
$arrayobject = new ArrayObject(new class {
public $a = 1;
}); // ArrayObject::__construct(): Using an object as a backing array for ArrayObject is deprecated
この使い方はするなとだいぶ前から言われていたのですが、ついにシステムで禁止されました。
Standard
The socket_set_timeout() alias function has been deprecated.
関数socket_set_timeoutが非推奨になりました。
stream_set_blockingを使いましょう。
そもそもソケット関数ではないのにsocketという名前がついていたのが謎。
Passing null to to readdir(), rewinddir(), and closedir() to use the last opened directory has been deprecated.
readdirなどディレクトリ関数に引数$dir_handleを渡さない使い方が非推奨になりました。
$dir = opendir('./');
var_dump(readdir()); // Deprecated: readdir(): Passing null is deprecated
引数を渡さない場合、これまでは『直近に開かれたディレクトリハンドル』が自動で渡されていました。
たいへん不自然極まりない動作なので禁止されます。
Passing integers outside the interval [0, 255] to chr() is now deprecated.
chrの引数に0-255以外の値を渡すことが非推奨になりました。
var_dump(chr(321)); // PHP Deprecated: chr(): Providing a value not in-between 0 and 255 is deprecated
これまでは引数を256で割った余りが使われていましたが、そんな値が来る時点でバグの可能性が高いので余計なことをしなくなりました。
Passing a string which is not a single byte to ord() is now deprecated,
ordの引数に1バイト文字以外を渡すことが非推奨になりました。
var_dump(ord('aa')); // Deprecated: ord(): Providing a string that is not one byte long is deprecated
こちらもバグの可能性が高いです。
The locally predefined variable $http_response_header is deprecated.
変数$http_response_headerが非推奨になりました。
file_get_contents('https://www.google.com');
var_dump($http_response_header); // Deprecated: The predefined locally scoped $http_response_header variable is deprecated
file_get_contentsなどを使用すると唐突に生えてくる謎の変数でした。
今後はかわりにhttp_get_last_response_headersを使いましょう。関数名長い。
XML
The xml_parser_free() function has been deprecated
関数xml_parser_freeが非推奨になりました。
PHP8.1以降、このメソッドは何もしていませんでした。
Changed Functions
動作に変更のあった関数。
Intl
IntlDateFormatter::setTimeZone()/datefmt_set_timezone() throws an IntlException on uninitialised classes/clone failures.
datefmt_set_timezoneは、失敗するとIntlExceptionを出すようになりました。
$formatter = IntlDateFormatter::create(null, IntlDateFormatter::FULL, IntlDateFormatter::FULL, 'UTC');
$formatter->setTimeZone('a');
// PHP8.5 Fatal error: Uncaught IntlException: IntlDateFormatter::setTimeZone(): No such time zone: "a"
// PHP8.4 エラー出ない
これまでは失敗したら単に無視されていました。
grapheme_extract() properly assigns $next value when skipping over invalid starting bytes.
grapheme_extractは、開始バイトが不正だった場合に引数$nextに適切な値を設定するようになりました。
$str = '👨👩👦👦';
$a = grapheme_extract($str, 1, GRAPHEME_EXTR_COUNT, 1, $next);
var_dump($next);
// PHP8.5 7
// PHP8.4 4
これまでは書記素の末尾ではなく先頭になることがありました。
ということらしいのですが、そもそも何が正しくて何が間違ってるのかすらわからない。
Locale:: methods throw a ValueError when locale inputs contain null bytes.
Localeの各メソッドは、引数にヌルバイトが入っていたらValueErrorを出すようになりました。
何かしらの脆弱性対策だと思います。
transliterator_get_error_code(), transliterator_get_error_message() TransLiterator::getErrorCode(), and TransLiterator::getErrorMessage() have dropped the false from the return type union.
TransLiterator::getErrorCodeほか一部関数の返り値からfalse型が削除されました。
実際にはfalseを返すことはありませんでした。
grapheme_strpos(), grapheme_stripos(), grapheme_strrpos(), grapheme_strripos(), grapheme_substr(), grapheme_strstr() and grapheme_stristr() functions add $locale parameter.
grapheme_strposなどのgrapheme関数に引数$localeが追加されました。
ja_JP-u-ks-identicなどの謎ロケールを使うことで、邊と邉を区別するかしないかなどを指定できるということらしいです。
コミッターによる解説を見てもらうのが手っ取り早いでしょう。
LDAP
ldap_get_option() now accepts a NULL connection
ldap_get_optionの引数$ldapがnullableになりました。
nullの場合はグローバル設定になります。
これはldap_set_optionと動作を合わせたものです。
libxml
libxml_set_external_entity_loader() now has a formal return type of true.
libxml_set_external_entity_loaderの返り値がtrue型になりました。
これまではbool型でした。
OpenSSL
openssl_public_encrypt() and openssl_private_decrypt() have a new parameter $digest_algo
openssl_public_encrypt・openssl_private_decryptに引数$digest_algoが追加されました。
OAEPパディングのハッシュアルゴリズムを指定するらしいです
openssl_sign() and openssl_verify() have a new parameter $padding
openssl_sign・openssl_verifyに引数$paddingが追加されました。
PSSパディングを使うことでより安全な暗号にできるそうです。
openssl_cms_encrypt() $cipher_algo parameter can be a string with the cipher name.
openssl_cms_encryptの引数$cipher_algoを文字列で直接指定できるようになりました。
これまではint型の定数値だけを設定可能でした。
PCNTL
pcntl_exec() now has a formal return type of false.
pcntl_execの返り値がfalse型になりました。
これまではbool型でした。
pcntl_waitid() takes an additional resource_usage argument
pcntl_waitidに引数$resource_usageが追加されました。
子プロセスに対して、プラットフォーム固有の情報を取得できるみたいです。
PDO_PGSQL
PDO::pgsqlCopyFromArray now supports Iterable inputs.
PDO::pgsqlCopyFromArrayの引数$rowがIterableを受け入れるようになりました。
とドキュメントには書いてあるのですが、この関数は上のほうにあったようにPdo\Pgsql::copyFromArrayに移行したのでそちらを使いましょう。
Pdo\Pgsql::setAttribute and Pdo\Pgsql::prepare support setting PDO::ATTR_PREFETCH to 0 which enters lazy fetch mode.
Pdo\Pgsql::setAttributeとprepareが遅延フェッチモードに対応しました。
オプションPDO::ATTR_PREFETCH=0を与えると遅延フェッチモードになります。
このモードではSQLの並列実行はできません。
PDO_SQLITE
SQLite PDO::quote() will now throw an exception or emit a warning, if the string contains a null byte.
Pdo\Sqlite::quoteは、ヌルバイトが含まれているとエラーを出すようになりました。
PDO::sqliteCreateCollation will now throw an exception if the callback has the wrong return type
Pdo\Sqlite::createCollationは、引数$callbackの戻り値の型が間違っている場合にエラーを出すようになりました。
PGSQL
pg_copy_from now supports Iterable inputs.
pg_copy_fromの引数$rowsがIterableを受け入れるようになりました。
pg_connect checks if the connection_string argument contains any null byte.
pg_connectは、ヌルバイトが含まれているとエラーを出すようになりました。
pg_close_stmt checks if the statement_name argument contains any null byte.
pg_close_stmtは、ヌルバイトが含まれているとエラーを出すようになりました。
POSIX
posix_ttyname sets last_error to EBADF when encountering an invalid file descriptor.
posix_ttynameは、無効なファイルディスクリプタを渡されると最後のエラーにEBADFを設定します。
posix_isatty raises an E_WARNING message when encountering an invalid file descriptor.
posix_isattyは、無効なファイルディスクリプタを渡されるとE_WARNINGを発生します。
posix_fpathconf checks invalid file descriptors and sets last_error to EBADF and raises an E_WARNING message.
posix_fpathconfは、無効なファイルディスクリプタを渡されると最後のエラーにEBADFを設定してE_WARNINGを発生します。
ところでファイルディスクリプタってなんだい。
posix_kill throws a ValueError when the process_id argument is lower or greater than what the platform supports
posix_kill・posix_setpgidは、引数$process_idがプラットフォームのサポート範囲外であればValueErrorを発生します。
posix_setrlimit throws a ValueError when the hard_limit or soft_limit arguments are lower than -1 or if soft_limit is greater than hard_limit.
posix_setrlimitは、$soft_limit < -1もしくは$hard_limit < -1もしくは$soft_limit > $hard_limitであればValueErrorを発生します。
Reflection
The output of ReflectionClass::__toString() for enums has changed to better indicate
ReflectionClass::__toStringは、列挙型に対して出力がわかりやすくなりました。
enum Suit: int
{
case Hearts = 1;
case Diamonds = 2;
case Clubs = 3;
case Spades = 4;
}
$c = new ReflectionClass('Suit');
var_dump($c->__toString());
/* PHP8.5
Enum [ <user> enum Suit: int implements UnitEnum, BackedEnum ]
- Enum cases [4] {
Case Hearts = 1
Case Diamonds = 2
Case Clubs = 3
Case Spades = 4
}
…
*/
/* PHP8.4
Class [ <user> final class Suit implements UnitEnum, BackedEnum ]
- Constants [4] {
Constant [ public Suit Hearts ] { Object }
Constant [ public Suit Diamonds ] { Object }
Constant [ public Suit Clubs ] { Object }
Constant [ public Suit Spades ] { Object }
}
…
*/
これまではオブジェクトがENUMかどうかはよく見ないとわからなかったのですが、PHP8.5では一目瞭然です。
The output of ReflectionProperty::__toString() for properties with hooks has changed
ReflectionProperty::__toStringは、プロパティフックを持つプロパティについて出力がわかりやすくなりました。
ReflectionAttribute::newInstance() can now throw errors for internal attributes
ReflectionAttribute::newInstanceは、不正なアトリビュートがあり、さらに[\DelayedTargetValidation]が設定されている場合に、実行時エラーが発生するようになりました。
Session
session_start is stricter in regard to the options argument.
session_startの引数チェックが厳密になりました。
引数$optionがハッシュマップでない場合はValueErrorが発生します。
引数の要素read_and_closeの値がint互換型でない場合はTypeErrorが発生します。
SNMP
snmpget, snmpset, snmp_get2, snmp_set2, snmp_get3, snmp_set3 and SNMP::__construct() throw a ValueError
snmpgetほかSNMP関数は、ホスト名が長すぎる、ヌルバイトが含まれている、ポート番号が0-65535の範囲外、タイムアウトとリトライ回数がマイナスだったり大きすぎる場合にValueErrorを発生します。
Sockets
socket_create_listen, socket_bind and socket_sendto throw a ValueError if the port is lower than 0 or greater than 65535,
socket_create_listenなどのソケット関数は、ポート番号が0-65535の範囲外の場合にValueErrorを発生します。
socket_addrinfo_lookup throws a TypeError if any of the hints values cannot be cast to int
socket_addrinfo_lookupは、引数$hintsがintキャストできない場合にTypeErrorを発生します。
socket_set_option with MCAST_LEAVE_GROUP/MCAST_LEAVE_SOURCE_GROUP options will throw an exception if the value isn't a valid object or array.
socket_set_optionの引数$levelがMCAST_LEAVE_GROUP・MCAST_LEAVE_SOURCE_GROUPだった場合、引数$optionsが配列でなければエラーが発生します。
socket_create/socket_bind can create AF_PACKET family sockets.
socket_createは、AF_PACKETのソケットを作成できるようになりました。
socket_getsockname gets the interface index and its string representation with AF_PACKET socket.
socket_getsocknameは、AF_PACKETソケットの情報を取得できるようになりました。
で、AF_PACKETってなに?
socket_set_option with multicast context throws a ValueError when the created socket is not of AF_INET/AF_INET6 family.
socket_set_optionは、マルチキャストコンテキストで、作成されたソケットがAF_INET/AF_INET6でない場合にValueErrorを発生するようになりました。
このあたりソケット自体を全く使ったことがないのでそもそもなんなのかよくわからない。
Tidy
tidy::__construct/parseFile/parseString now throws a ValueError if the configuration contains an invalid value or attempts to set a read-only internal entry
tidy::__constructなどパース関数は、引数$configに無効な値を渡した際にValueErrorを発生するようになりました。
Zlib
The "use_include_path" argument for the gzfile, gzopen and readgzfile functions has been changed from int to boolean.
gzfileなどgz関数の引数$use_include_pathの型が、intからboolになりました。
gzfile, gzopen and readgzfile functions now respect the default stream context.
同じくgz関数は、デフォルトのストリームコンテキストを尊重するようになりました。
具体的にどういうことなのかはよくわからない。
New Functions
新しい関数・メソッド。
Core
get_error_handler()
ユーザが定義したエラーハンドラを取得します。
get_exception_handler()
ユーザが定義した例外ハンドラを取得します。
clone
cloneがキーワードから関数になりました。
Closure::getCurrent()
現在実行中のクロージャを取得します。
Curl
curl_multi_get_handles()
CurlMultiHandleにアタッチされている全てのCurlHandleを取得します。
curl_share_init_persistent()
DOM
Dom\Element::getElementsByClassName() / Dom\Element::insertAdjacentHTML()
解説が何もないのですが、まあ名前からしてgetElementsByClassName・insertAdjacentHTMLでしょう。
Enchant
enchant_dict_remove_from_session()
enchant_dict_add_to_sessionで追加した単語を削除します。
enchant_dict_remove()
単語を除外リストに追加します。
そもそもEnchantを使っている人なんてどんだけいるんだ?
Intl
locale_is_right_to_left() / Locale::isRightToLeft()
右から左へ書く言語にtrueを返します。
grapheme_levenshtein()
Opcache
opcache_is_script_cached_in_file_cache()
解説が一切ないのですが、どうやらOPcacheでキャッシュファイルがつくられたかどうかを調べる関数のようです。
opcache_is_script_cachedはメモリにキャッシュされているかを調べる関数で、元々これに機能追加しようとしたけど最終的に別関数になったみたい。
Pdo\Sqlite
Pdo\Sqlite::setAuthorizer()
SQLite3::setAuthorizerのPDO版です。
PGSQL
pg_close_stmt()
DEALLOCATEでプリペアドSQLの割り当てを解除した後で、再利用できるみたいです。
pg_service()
接続中のサービス名を返します。
なんのサービス名かは不明。
Reflection
ReflectionConstant::getFileName()
定数が定義されたファイルを取得します。
ReflectionConstant::getExtension() / ReflectionConstant::getExtensionName()
定数が定義された拡張モジュールを取得します。
ReflectionConstant::getAttributes()
定数に設定されているアトリビュートを取得します。
ReflectionProperty::getMangledName()
プロパティの修飾名を取得します。
class TestClass {
public $publicProp = 1;
protected $protectedProp = 1;
private $privateProp = 1;
}
var_dump(
new ReflectionProperty('TestClass', 'publicProp')->getMangledName(), // "publicProp"
new ReflectionProperty('TestClass', 'protectedProp')->getMangledName(), // "%0*%0protectedProp"
new ReflectionProperty('TestClass', 'privateProp')->getMangledName(), // "%0TestClass%0privateProp"
);
protected・privateプロパティはコンパイル時に内部的な名前が変わるらしく、それを追跡できるみたいです。
Sqlite
Sqlite3Stmt::busy()
ステートメントがfetch中であり、まだ終わってない場合にtrueを返します。
Standard
array_first() / array_last()
配列の最初と最後の値を取得します。
array_first([1, 2, 3]); // 1
array_last( [1, 2, 3]); // 3
むかーしPHP7.3でarray_key_first・array_key_lastが実装されたのですが、その際array_value_first・array_value_lastは却下されてしまいました。
たぶん名前が悪かったのでしょう。
その後長い時を経てPHP8.5でついに受理されました。
New Classes and Interfaces
新しいクラス・インターフェイス。
Core
NoDiscard
NoDiscardアトリビュートです。
帰り値の受け取りを強制します。
DelayedTargetValidation
コンパイルエラーを実行時エラーに変更するDelayedTargetValidationアトリビュートです。
一般人が使用することはないと思います。
Curl
CurlSharePersistentHandle
関数curl_share_init_persistentで作成されるCurlハンドルです。
Filter
Filter\FilterException / Filter\FilterFailedException
フィルタ関数にFILTER_THROW_ON_FAILUREを渡したときに発生する例外です。
URI
Uri\XXX
RFC3986に基いてURIを正しく取り扱う機能で導入されるクラス群です。
Uri\UriException・Uri\InvalidUriException・Uri\UriComparisonMode・Uri\Rfc3986\Uri・Uri\WhatWg\InvalidUrlException・Uri\WhatWg\UrlValidationErrorType・Uri\WhatWg\UrlValidationError・Uri\WhatWg\Urlが追加されます。
Removed Extensions and SAPIs
削除されたエクステンション・SAPIはありません。
Other Changes to Extensions
エクステンションのその他の変更。
Curl
curl_easy_setopt with CURLOPT_FOLLOWLOCATION option's value no longer is treated as boolean but integer
CURLOPT_FOLLOWLOCATIONはbool型からint型になりました。
新機能で解説しているCURLFOLLOW_OBEYCODE・CURLFOLLOW_FIRSTONLY・CURLFOLLOW_ALLを設定可能です。
Fileinfo
Upgraded file from 5.45 to 5.46.
同梱されているlibmagicのバージョンが5.45から5.46になりました。
The return type of finfo_close() has been changed to true, rather than bool
finfo_closeの返り値はbool型からtrue型になりました。
そもそも非推奨になったので書き換えるのではなく削除しましょう。
Intl
Intl's internal error mechanism has been modernized
Intlの内部エラーメカニズムを改善しました。
どのエラーがどこで発生したのかがわかりやすくなりました。
Lexbor
An always enabled lexbor extension is added.
Lexbor拡張モジュールが常に有効になりました。
これはPHP8.4で実装された新たなDOM機能のために使用されるライブラリです。
PHPはDOMの解析に話題のlibxml2を使っているのですが、それだけでは再現できない機能のために新たに導入されました。
もしかしたらこの機会に、今後全てのDOM機能をLexborに持っていくみたいなこともあるかもしれませんね。
Opcache
The Opcache extension is now always built into the PHP binary and is always loaded.
Opcache拡張機能が常にロードされるようになりました。
これはPHPコアが使用するためであり、ユーザランドからの使用可否は引き続きopcache.enableで制御可能です。
URI
An always enabled uri extension is added that can be used for handling URIs and URLs according to RFC 3986 and WHATWG URL.
RFC3986およびWHATWG URLに基いてURLを正しく取り扱うUriが導入されました。
PHPの場合、CurlはRFC3986に従い、FILTER_VALIDATE_URLはRFC2396に従い、そしてparse_urlは気分でパースするなどアバウトなところがありました。
Uriを使うと正確なパース、そして変換が可能になります。
正直底まで必要な人がどこまでいるのかはよくわからない。
PDO_Sqlite
Increased minimum release version support from 3.7.7 to 3.7.17.
サポートするSQLiteの最低バージョンが3.7.7から3.7.17に変更されました。
Readline
The return types of readline_add_history(), readline_clear_history(), and readline_callback_handler_install() have been changed to true
readline_add_history・readline_clear_history・readline_callback_handler_installの返り値がbool型からtrue型になりました。
Reflection
ReflectionConstant is no longer final.
ReflectionConstantがfinalではなくなりました。
New Global Constants
新しいグローバル定数。
Core
PHP_BUILD_DATE・PHP_BUILD_PROVIDER
名前のとおりビルド情報が入っています。
Curl
CURLINFO_USED_PROXY・CURLINFO_HTTPAUTH_USED・CURLINFO_PROXYAUTH_USED・CURLINFO_CONN_ID・CURLINFO_QUEUE_TIME_T・CURLOPT_INFILESIZE_LARGE・CURLFOLLOW_ALL・CURLFOLLOW_OBEYCODE・CURLFOLLOW_FIRSTONLY
最近Curlに追加された定数をそのままPHPに持ってきたようです。
Filter
FILTER_THROW_ON_FAILURE
Intl
DECIMAL_COMPACT_SHORT・DECIMAL_COMPACT_LONG
OpenSSL
OPENSSL_PKCS1_PSS_PADDING・PKCS7_NOSMIMECAP・PKCS7_CRLFEOL・PKCS7_NOCRL・PKCS7_NO_DUAL_CONTENT
POSIX
POSIX_SC_OPEN_MAX
Sockets
IPPROTO_ICMP・IPPROTO_ICMPV6・TCP_FUNCTION_BLK・TCP_FUNCTION_ALIAS・TCP_REUSPORT_LB_NUMA・TCP_REUSPORT_LB_NUMA_NODOM・TCP_REUSPORT_LB_NUMA_CURDOM・TCP_BBR_ALGORITHM・AF_PACKET・ETH_P_IP・ETH_P_IPV6・ETH_P_LOOP・ETH_P_ALL・IP_BINDANY・SO_BUSY_POLL・UDP_SEGMENT・SHUT_RD・SHUT_WR・SHUT_RDWR
このへん定数名が列挙してあるだけで、具体的にどれが何なのかよくわからないのが残念。
Tokenizer
T_VOID_CAST・T_PIPE
Standard
IMAGETYPE_SVG
Changes to INI File Handling
iniファイルの変更点。
Core
Added fatal_error_backtraces to control whether fatal errors should include a backtrace.
ini設定fatal_error_backtracesが追加されました。
エラー発生時のバックトレースの有効無効を設定します。
デフォルトは1で有効です。
Added startup-only max_memory_limit INI setting to control the maximum memory_limit
ini設定max_memory_limitが追加されました。
ini_setで上げられるmemory_limitの上限です。
共有サーバなどでini_set('memory_limit', -1);とかされてしまうのを防ぎます。
Opcache
Added opcache.file_cache_read_only to support a read-only opcache.file_cache directory
ini設定opcache.file_cache_read_onlyが追加されました。
読み取り専用ファイルシステム(ReadOnly Dockerコンテナなど)で使用できるみたい。
The default value of opcache.jit_hot_loop is now 61
ini設定opcache.jit_hot_loopのデフォルト値が61になりました。
よくわからないんだけどループ回数の倍数になるとよくないみたい。
Changing opcache.memory_consumption when OPcache SHM is already set up will now correctly report a failure
OPcache SHMが既に有効な状態でini設定opcache.memory_consumptionを変更するとエラーが出るようになりました。
OpenSSL
Added openssl.libctx to select the OpenSSL library context type.
ini設定openssl.libctxが追加されました。
OSSL_LIB_CTXを設定できるみたい。
もちろんOSSL_LIB_CTXが何なのかはわからない。
Windows Support
Windowsのサポート。
The configuration variables PHP_VERSION, PHP_MINOR_VERSION, and PHP_RELEASE_VERSION are now always numbers.
各定数値がかならず数値になりました。
これまでは、ビルド環境によっては文字列になることがあったようです。
phpize builds now reflect the source tree in the build dir
phpizeコマンドは、ビルドディレクトリ内のソースツリーを反映するようになりました。
phpizeとか大昔にlibpuzzleに使ったきりだからさっぱりわかんね。
--enable-sanitizer is now supported for MSVC builds
MSVCビルドでコマンドラインオプション--enable-sanitizerがサポートされました。
ASanが使えるようになるみたい。
すごい。
The --with-uncritical-warn-choke configuration option for clang builds is no longer supported.
clangビルドでコマンドラインオプション--with-uncritical-warn-chokeがサポートされなくなりました。
どうも一部のコンパイルエラーを無視するオプションみたいですが、その決め方が適当だったから、ちゃんと用意されているCFLAGSを使えということみたいです。
そもそも削除されたという記事しか見当たらない超マイナー機能です。
実装されたという記載があったのは内部向けドキュメントだけで、ユーザ向けドキュメントには全く書かれていませんでした。
COM. The extension is now build shared by default
COMはデフォルトで共有ビルドされるようになりました。
これまでは静的ビルドがデフォルトでした。
FFI. It is no longer necessary to specify the library when using FFI::cdef() and FFI::load().
FFI::cdefを使用する際に、ライブラリを指定しなくてもよくなりました。
でもプロダクション環境では使用するなと書いてありました。
Streams. If only pipe streams are contained in the $read array, and the $write and $except arrays are empty, stream_select() now behaves similar to POSIX systems
stream_selectの引数$readがパイプストリームだけであり、引数$write・$exceptが空の場合、POSIXと同じ動作をするようになりました。
状況が限定的すぎてどういうことなのかわからない。
Other Changes
その他の変更。
Core
The high resolution timer (hrtime()) on macOS now uses the recommended clock_gettime_nsec_np(CLOCK_UPTIME_RAW) API
hrtimeは、macOSでのタイマーをmach_absolute_timeからclock_gettime_nsec_np(CLOCK_UPTIME_RAW)に変更しました。
CLI/CGI
The -z or --zend-extension option has been removed as it was non-functional.
コマンドライン引数-z・--zend-extensionは削除されました。
元々動いてなかったらしいです。
かわりに-d zend_extension=<path>を使いましょう。
PDO_ODBC
The fetch behaviour for larger columns has been changed.
PDO_ODBCで長い列をfetchできるようになりました。
大きな列をfetchしようとした場合、ODBCは何故か256バイト区切りになるので大きいデータを正常にfetchできないことがあったそうです。
なんかすごいがんばって解決したみたい。
Performance Improvements
パフォーマンスの向上について。
Core
Remove OPcodes for identity comparisons against booleans, particularly for the match(true) pattern.
bool型との比較、特にmatch(true)のOPコードを削除しました。
これは変換せずに比較するから比較が高速化する、という意味でいいんだろうか。
Add OPcode specialization for === [] and !== [] comparisons.
=== []・!== []の比較を特殊化しました。
Creating exception objects is now much faster.
Exceptionオブジェクトの生成が大幅に高速化しました。
The parts of the code that used SSE2 have been adapted to use SIMD with ARM NEON as well.
SSE2を使っている部分は、ARMでもNEONを使うようにしました。
Introduced the TAILCALL VM
TAILCALL VMを導入しました。
x86_64・aarch64でC19以降でコンパイルする場合に有効になります。
これによってコンパイルされたPHPバイナリは、GCCでビルドされたバイナリと同様の速度になります。
ってあるんだけどTAILCALL VMがなんのことかよくわからない。
末尾再帰呼び出し最適化とは関係ないよね?
Intl
Now avoids creating extra string copies when converting strings for use in the collator.
言語を考慮した文字列比較を行う際に、不要な文字列のコピーをしないようになりました。
MBString
The parts of the code that used SSE2 have been adapted to use SIMD with ARM NEON as well.
SSE2を使っている部分は、ARMでもNEONを使うようにしました。
Opcache
Improved performance of fetching TLS variables in JIT'ed code in non-Glibc builds.
Glibc以外のビルド環境で、JITコードからTLS変数を取得する速度が向上しました。
TLS変数ってなに?
ReflectionProperty
Improved performance of the following methods: getValue(), getRawValue(), isInitialized(), setValue(), setRawValue().
ReflectionPropertyの各メソッドのパフォーマンスが向上しました。
SPL
Improved performance of dimension accessors and methods of SplFixedArray.
SplFixedArrayへの値アクセスと、メソッドのパフォーマンスが向上しました。
Standard
Improved performance of array functions with callbacks (array_find, array_filter, array_map, usort, ...).
array_findなど、引数でコールバックを受け取る配列関数のパフォーマンスが向上しました。
Improved performance of urlencode() and rawurlencode().
urlencodeとrawurlencodeのパフォーマンスが向上しました。
Improved unpack() performance with nameless repetitions by avoiding creating temporary strings and reparsing them.
unpackのパフォーマンスが向上しました。
Improved pack() performance.
packのパフォーマンスが向上しました。
Minor improvements in array_chunk() performance.
array_chunkのパフォーマンスが少し向上しました。
XMLReader
Improved property access performance.
XMLReaderのプロパティアクセスのパフォーマンスが向上しました。
XMLWriter
XMLWriterのパフォーマンスが向上し、メモリ消費量も削減しました。
パフォーマンスの項目は向上したとしか書かれていないので、具体的に何をやってどれくらい早くなったとかも書いてほしいところですね。
感想
とりあえず最大の目玉はパイプ演算子でしょうか。
これによって複雑な関数の書き心地が圧倒的によくなります。
実際はパイプ演算子だけだとすこし力不足な部分もあるのですが、既にPHP8.6で部分適用が導入されることが決まっています。
この相乗効果によって、PHPは関数型に匹敵する表現力を手に入れたと言っても過言ではないでしょう(過言)。