PHP

PHP 8.5の変更点と新機能まとめ|リリース日・主要機能・非推奨と移行ポイント

PHP 8.5は2025年11月20日に正式リリースされたメジャーアップデートで、コードの書き方そのものを変える|>(パイプ演算子)や、イミュータブルなオブジェクト更新を簡潔にするclone()構文、戻り値の無視を警告する#[\NoDiscard]属性、標準化されたURI/URL解析拡張などが加わりました。この記事ではPHP 8.5の変更点を、追加された新機能だけでなく非推奨・破壊的変更と移行時の注意点まで含めて、実際に動くコードとともに整理します。リリース日やサポート期限、8.5.5などのパッチ版の位置づけも先にまとめます。

まとめ:PHP 8.5の変更点の要点

  • PHP 8.5.0は2025年11月20日にリリース。バグ修正(アクティブサポート)は2027年12月31日まで、セキュリティ修正は2029年12月31日まで。
  • 新構文の目玉は|>(パイプ演算子)とclone($obj, [...])(clone with)。読みにくいネストや読み取り専用クラスの複製が簡潔になる。
  • #[\NoDiscard]属性で戻り値の使い忘れを警告できる。定数へのアトリビュート付与や、定数式でのクロージャ利用も解禁された。
  • parse_url()に代わる標準のUri\Rfc3986\Uri / Uri\WhatWg\Url拡張が同梱され、規格準拠のURL解析ができる。
  • 性能・運用面では永続的なcURL共有ハンドル(curl_share_init_persistent())と、致命的エラーのスタックトレース(fatal_error_backtraces、既定ON)が効く。
  • 非推奨・破壊的変更もあるため、アップグレード前に該当箇所の洗い出しが必須。後半の移行の章で列挙する。

PHP 8.5のリリース日とサポート期限

PHP 8.5.0の正式リリース(GA)は2025年11月20日です。PHPのリリースサイクルでは各マイナーバージョンに2年のアクティブサポート(バグ修正)と、その後2年のセキュリティ修正が付きます。PHP 8.5では次の日程です。php8.5.5のようなパッチ版は、この期間中に毎月出るバグ・セキュリティ修正版で、機能追加ではなく安定性向上を目的とした通常のマイナーリリースです。

バージョン GA アクティブサポート終了 セキュリティ修正終了
PHP 8.5 2025-11-20 2027-12-31 2029-12-31
PHP 8.4 2024-11-21 2026-12-31 2028-12-31
PHP 8.3 2023-11-23 2025-12-31(終了) 2027-12-31

本番環境をPHP 8.5へ上げる主な動機は、新機能そのものよりもサポート期間の確保です。すでにアクティブサポートが切れた8.3以前を使っているなら、非推奨・破壊的変更を確認したうえで8.5への移行計画を立てるのが実務的な判断になります。性能面のチューニングを合わせて見直すなら、opcacheの設定を扱ったOPcacheとは?読み方とPHP 8.5の変更点・設定・確認方法も参照してください。

コードの書き方を変える新構文

パイプ演算子(|>)による処理の左から右への連結

|>は左の値を右の呼び出し可能オブジェクトに渡し、結果をさらに次へ流すパイプ演算子です。従来はstr_replace(' ', '-', strtolower(trim($s)))のように内側から読む必要がありましたが、パイプで実行順のとおり左から右へ書けるようになり、中間変数も不要になります。

$slug = "  Hello World  "
    |> trim(...)
    |> strtolower(...)
    |> (fn($s) => str_replace(" ", "-", $s));
// $slug === "hello-world"

右側には第一級callable記法(trim(...))やアロー関数、名前付き関数を置けます。各ステップは値を1つだけ受け取る単項の呼び出しである必要があり、複数引数を渡したい場合はアロー関数でラップします。

clone with構文によるイミュータブルな更新

PHP 8.5ではcloneclone($object, [プロパティ => 値])の形で第2引数を取れるようになりました。複製と同時に一部プロパティだけを差し替えられるため、readonlyクラスで「一部だけ変えた新しいインスタンス」を返すwith系メソッドが素直に書けます。差し替えは__clone()の呼び出し後に行われ、可視性やプロパティフックも尊重されます。

final class Money {
    public function __construct(
        public readonly int $amount,
        public readonly string $currency,
    ) {}

    public function withAmount(int $amount): static {
        return clone($this, ["amount" => $amount]);
    }
}

従来はcloneした後に個別代入が必要で、readonlyプロパティは複製後も再代入できず回避策を強いられていました。clone withはこの定型を一行に畳み込みます。

#[\NoDiscard]属性による戻り値の使い忘れ警告

#[\NoDiscard]を関数・メソッドに付けると、その戻り値を使わずに呼び出した場合に警告が出ます。検証結果やエラーコードなど「必ず受け取って処理すべき戻り値」を無視するバグを、実行時の警告で気づけます。意図的に破棄するときは(void)キャストで警告を抑制できます。

#[\NoDiscard("戻り値の検証結果を確認してください")]
function validate(string $input): bool { /* ... */ }

validate($input);        // Warning: 戻り値が未使用
(void) validate($input); // 意図的な破棄は警告なし

定数へのアトリビュート付与と定数式でのクロージャ

コンパイル時に決まる非クラス定数(constdefine()相当)にアトリビュートを付けられるようになり、定数にメタデータを添えて設計時の参照情報として使えます。あわせて定数式のなかでクロージャや第一級callableを使えるようになりました。例えばアトリビュートの引数にコールバックを渡せます。ただしクロージャはstatic指定が必須で、useによる外部スコープの変数取り込みはできません。

#[Deprecated]
const LEGACY_MODE = 1;

#[Validate(static fn($v) => $v > 0)]
class Config { /* ... */ }

静的プロパティの非対称可視性

PHP 8.4でインスタンスプロパティに導入された非対称可視性(読み取りと書き込みで可視性を分ける記法)が、PHP 8.5では静的プロパティにも使えるようになりました。クラス外からは読み取り専用にしつつ、書き込みはクラス内部に限定する、といった制御を静的プロパティでも表現できます。

class Counter {
    public private(set) static int $count = 0;
    public static function inc(): void { self::$count++; }
}
// 読み取りは可、外部からの $count 書き込みは不可

標準ライブラリ・APIの強化

規格準拠のURI/URL拡張(Uri\Rfc3986\Uri / Uri\WhatWg\Url)

長年parse_url()が抱えていた曖昧さを解消するため、PHP 8.5には規格準拠のURI拡張が同梱されました。インストール不要で常に利用でき、RFC 3986準拠のUri\Rfc3986\Uriと、WHATWG URL標準準拠のUri\WhatWg\Urlの2クラスを提供します。前者はスキームのない相対URIも扱え、後者はスキーム必須のURLを自動正規化します。不正な入力では例外の代わりにnullを返す静的メソッドparse()も用意されています。

use Uri\Rfc3986\Uri;

$uri = new Uri("https://example.com:8080/path?q=1#top");
echo $uri->getScheme(); // "https"
echo $uri->getHost();   // "example.com"
echo $uri->getPort();   // 8080

$maybe = Uri::parse($userInput); // 失敗時は null

array_first() / array_last() による配列端の直接取得

配列の先頭・末尾の値を取り出すarray_first()array_last()が追加されました。これまで$array[array_key_first($array)]のように書いていた処理が一関数で済み、空配列のときはnullを返します。reset()end()と違って内部ポインタを動かさないため、副作用を気にせず使えます。

$first = array_first($items); // 先頭の値(空なら null)
$last  = array_last($items);  // 末尾の値(空なら null)

get_error_handler() / get_exception_handler() によるハンドラの取得

set_error_handler()set_exception_handler()で登録した現在のハンドラを、実行時に取得するget_error_handler()get_exception_handler()が新設されました。既存のハンドラを一時的に差し替えて元に戻す、といったラップ処理を安全に書けます。未登録の場合はnullが返ります。

$prev = get_exception_handler();       // 現在のハンドラを退避
set_exception_handler($myHandler);
// ... 一時的な処理 ...
set_exception_handler($prev);          // 元に戻す

このほか、複数言語の並び表現を作るIntlListFormatterクラス、検証失敗時にFilter\FilterFailedExceptionを投げるFILTER_THROW_ON_FAILUREフラグ、cURLハンドルを一括取得するcurl_multi_get_handles()などの実務的なAPIも追加されています。

パフォーマンスと運用面の改善

永続的なcURL共有ハンドルによる通信の高速化

curl_share_init_persistent()は、リクエストをまたいで生き続けるcURL共有ハンドルを作ります。通常のcurl_share_init()で作ったハンドルはリクエスト終了時に破棄されますが、永続版はDNS解決結果やコネクション、SSLセッションをプロセス内で使い回すため、外部APIへ何度もアクセスする処理で接続確立のコストを削減できます。同じ共有オプションの永続ハンドルがあれば再利用されます。

$share = curl_share_init_persistent([
    CURL_LOCK_DATA_DNS,
    CURL_LOCK_DATA_SSL_SESSION,
]);

$ch = curl_init("https://api.example.com/");
curl_setopt($ch, CURLOPT_SHARE, $share);

戻り値はCurlSharePersistentHandleオブジェクトで、CURLOPT_SHARE経由で利用します。安全のためCURL_LOCK_DATA_COOKIEは指定できず、渡すとValueErrorになります(Cookieをリクエスト間で共有するとユーザー間で混ざる危険があるため)。PHPの実行エンジン自体を見直して性能を底上げしたい場合は、FrankenPHPとは何か?モダンなPHP実行エンジンの概要と誕生背景も検討候補になります。

致命的エラーのスタックトレースによる原因特定

PHP 8.5では致命的エラー(メモリ上限超過やタイムアウトなど)でもスタックトレースが出力されるようになりました。従来はエラーメッセージだけで発生箇所が追いにくかった場面で、呼び出し履歴から原因を特定できます。この挙動はfatal_error_backtracesというINIディレクティブで制御し、既定で有効(1)です。引数を含めたくない場合はzend.exception_ignore_argsと併用します。

; php.ini
fatal_error_backtraces = 1   ; 既定で有効。0で無効化

非推奨・破壊的変更と移行時の注意点

新機能に目が行きがちですが、アップグレードで実害が出るのは非推奨(Deprecated)・破壊的変更の側です。PHP 8.5で非推奨になった主なものは次のとおりで、いずれも将来のメジャー版で削除される前提のため、8.5移行のタイミングで洗い出しておくべきです。

対象 変更 対応
非正規なスカラー型キャスト 非推奨 正規の型名でキャストする
mysqli_execute() 別名が非推奨 mysqli_stmt_execute()を使う
curl_close() / curl_share_close() 非推奨(不要化) 呼び出しを削除(自動解放)
xml_parser_free() 非推奨 呼び出しを削除
socket_set_timeout() 非推奨 stream_set_timeout()を使う
MHASH_*定数 非推奨 hash()系へ移行

移行の実務では、まず非推奨警告をログで拾うことから始めます。テスト環境でerror_reportingE_DEPRECATEDを含め、出力される警告を潰していくのが確実です。コードを実行せずに静的解析で問題箇所を先回りして検出したい場合は、PsalmとPHPStanの比較:機能や使用感の違いを検証を参考に、型・非推奨APIのチェックをCIへ組み込むと移行の手戻りが減ります。非同期・並行処理まわりのコードを持つプロジェクトは、PHP 8.1のFibersを利用した非同期処理のメリットと活用法で扱う挙動とあわせて回帰テストの対象にしてください。

破壊的変更は影響範囲が限定的なものが中心ですが、出力バッファのカスタムハンドラの挙動やスカラーキャストの厳格化など、既存コードが暗黙に依存していた部分に触れる可能性があります。本番反映の前に、対象バージョンでの通しテストを必ず実施してください。

よくある質問

PHP 8.5のリリース日はいつですか?

PHP 8.5.0の正式リリース(GA)は2025年11月20日です。以降は8.5.18.5.5のように、バグ・セキュリティ修正のパッチ版が定期的に公開されています。

PHP 8.5.5とは何ですか。8.5.0と機能は違いますか?

8.5.5は8.5系のパッチリリースで、8.5.0からの機能追加はありません。バグ修正とセキュリティ修正のみが入る安定版なので、8.5系を使うなら常に最新のパッチ版に上げておくのが推奨です。

PHP 8.4との一番大きな違いは何ですか?

構文面ではパイプ演算子|>とclone with(clone($obj, [...]))が8.5の目玉です。8.4で入った非対称可視性が静的プロパティへ拡張された点や、規格準拠のURI拡張が標準同梱された点も8.5固有の変更です。

PHP 8.5にすると性能は上がりますか?

言語全体が一律に速くなるわけではありませんが、外部API通信では永続cURL共有ハンドル、エラー調査では致命的エラーのスタックトレースが効きます。OPcacheの設定を含めた実行環境のチューニングと合わせて評価するのが現実的です。

PHP 8.5へアップグレードする際の注意点は?

非推奨・破壊的変更の洗い出しが最優先です。E_DEPRECATEDを有効にして警告を潰し、静的解析と通しテストを本番反映前に実施してください。サポート期限(アクティブ2027年末・セキュリティ2029年末)も移行判断の材料になります。

関連記事

資料請求

RELATED POSTS 関連記事