公開日
PHP 8.6 が、2026年11月19日にリリースされる予定です。
新しい書き方がいくつか増えます。
それより大事なのは、保守しているサイトに影響しそうな変更です。
それぞれ「なぜ変わったのか」と一緒にまとめました。
⚠ リリース前の情報です。2026年11月11日の時点で、正式版はまだ出ていません。正式版が出たら、この記事も見直します。
関数を呼ぶときに、引数の一部を ? にしておくと、残りの引数を受け取る関数ができます。
文字で書くと分かりにくいので、コードで見たほうが早いです。
// これまで:型まで全部書き直す必要があった
$result = array_map(
static fn(string $s): string => str_replace('hello', 'hi', $s),
$arr
);
// PHP 8.6
$result = array_map(str_replace('hello', 'hi', ?), $arr); ? は「ここに1つ入る」、... は「残り全部」という意味です。
背景アロー関数(fn)で書くと、元の関数の引数の型や名前を、もう一度書き写すことになります。書く人にも読む人にも、ただの手間でした。PHP 8.1 で入った strlen(...) のような書き方(第一級callable)の延長で、PHP 8.5 で入ったパイプ演算子(|>)と組み合わせやすくする狙いもあります。
値が範囲の外なら、近いほうの端に寄せて返す関数です。
// これまで
$percent = max(0, min(100, $value));
// PHP 8.6
$percent = clamp($value, min: 0, max: 100); min が max より大きいときは、エラー(ValueError)になります。
背景これまでは min() と max() を組み合わせるか、フレームワークの関数を使うのが普通でした。min と max を逆に書いても気づけない、という弱点もありました。ほかの多くの言語には、もともと同じ関数があります。
「1分30秒」のような時間の長さを、ナノ秒の精度で表せるクラスです。
$timeout = \Time\Duration::fromMinutes(1)
->add(\Time\Duration::fromSeconds(30)); // 1分30秒 背景PHP の関数は、時間を「秒の int」「マイクロ秒の int」「秒の float」など、ばらばらの形で受け取っていました。日付の間隔を表す DateInterval は、月や日を含むので、タイムアウトのような「きっちり何秒」には向いていませんでした。
※ 「sleep() に Duration を渡せる」と紹介している記事もありますが、RFC では仮の例です。今回、今までの関数が Duration を受け取れるようになるわけではありません(新しい Polling API だけが受け取ります)。
final class Yen
{
public readonly string $code = 'JPY'; // PHP 8.5 まではエラー
} 背景readonly が入ったとき、初期値は「定数と同じで、意味がない」とされて禁止されていました。PHP 8.4 でインターフェースにプロパティを書けるようになり、「実装するクラスごとに決まった値を持たせる」使い道ができたので、解禁されました。
$query->orderBy('created_at', SortDirection::Descending); 背景並び順は、SORT_ASC、'ASC' という文字、true / false など、場所によって書き方がばらばらでした。フレームワークもそれぞれ自分で作っていたので、PHP 本体に1つ用意して、そろえやすくしました。
#[\Override] を、クラスの定数や enum の case にも付けられる__debugInfo() を書ける(var_dump() の表示を変えられる)json_last_error_msg() のエラーに、壊れている場所が出るmysqli_quote_string()、grapheme_strrev()(絵文字なども崩さずに文字列を逆にする)などの関数Io\Poll)いちばん影響がありそうなのが、ここです。
| session.use_strict_mode | 0 → 1(知らないセッション ID を受け付けない) |
|---|---|
| session.cookie_httponly | 0 → 1(JavaScript からセッションの Cookie を読めない) |
| session.cookie_samesite | なし → Lax(ほかのサイトからの POST では Cookie を送らない) |
背景3つとも、セキュリティの攻撃(セッションの乗っ取り・XSS・CSRF)を防ぐための設定です。Django、ASP.NET、Laravel、Symfony などは、もともと安全な側が初期値です。PHP 本体は、ずっと古い初期値のままでした。
注意したいのは、ほかのサイトから POST で戻ってくる仕組みです。
たとえば、決済や外部のログインのページから、POST でサイトに戻ってくる作りだと、セッションの Cookie が送られず、ログインや入力の途中の状態が消えることがあります。
JavaScript でセッションの Cookie を読んでいる作りも、読めなくなります。
※ これは php.ini に何も書いていないときの値です。レンタルサーバーの php.ini や、プログラムの中で値を指定していれば、そちらが使われます。
非推奨は、すぐに動かなくなるわけではありません。
警告(Deprecated)が出るようになり、PHP 9 でなくなる予定のものです。
よく出てきそうなものから、書き換え方と一緒に並べます。
日本のサイトで、いちばん気をつけたいものです。日本語の正規表現のために、昔から使われてきた関数なので、古いサイトほど残っています。
区切りの / と、日本語を正しく扱うための u を付けて書き換えます。
// 非推奨(全角・半角のスペースを1つにまとめる)
$name = mb_ereg_replace('[ \s]+', ' ', $name);
// 書き換え
$name = preg_replace('/[ \s]+/u', ' ', $name); 背景mb_ereg 系が中で使っている正規表現のライブラリ(Oniguruma)の開発が、2025年4月に終わったためです。
try で起きた例外が消えて、何もなかったように値が返ってしまいます。finally は後片づけだけにして、return は外に出します。
// 非推奨:保存に失敗しても、例外が消えて 'OK' が返る
function save(): string
{
try {
throw new RuntimeException('保存に失敗');
} finally {
return 'OK';
}
}
// 書き換え
function save(): string
{
try {
$result = write();
} finally {
unlock();
}
return $result;
} 背景エラーも警告も出ないまま失敗が消えるので、あとで原因をたどれなくなるためです。よく使われているライブラリの中にも、実際に例外を消してしまう書き方が見つかったそうです。
// 非推奨(右が書き換え)
is_double($price); // → is_float($price)
is_integer($count); // → is_int($count)
is_long($count); // → is_int($count)
doubleval($input); // → floatval($input) 背景同じ働きの関数に、名前が2つあってややこしいためです。
返ってくる値が、文字列から整数に変わります。値を保存したり、文字列として比べたりしている場合は注意します。
// 非推奨(32文字の文字列が返る)
$key = spl_object_hash($user);
// 書き換え(整数が返る)
$key = spl_object_id($user); 背景「hash」という名前なのに、オブジェクトの中身から作った値ではないためです。
SplFileObject の fgetcsv() などの CSV のメソッド。作りが古く、直しにくくなっているため(関数の fgetcsv() は対象外)。CSV の取り込みや書き出しがある業務システムは、確かめておくと安心です__construct() で値を返す。返した値は、もともと使われないためdefine() の3つ目の引数。大文字・小文字を区別しない定数は、すでに PHP 8.0 で使えなくなっているためhttp_build_query() や array_walk() にオブジェクトを渡す。get_object_vars() で配列にしてから渡すtrim() が、改ページ(\f)も空白として削るようになる。JavaScript や Python など、ほかの言語に合わせたpreg_grep() は、エラーのときに途中までの配列ではなく false を返す。ほかの preg_* と同じになったfile_put_contents()・fclose()・copy() は、書き込みの最後に失敗したとき false を返す。これまでは、失敗しても気づけなかった| PHP 8.2 | セキュリティの修正は 2026年12月31日で終了 |
|---|---|
| PHP 8.3 | セキュリティの修正は 2027年末まで |
| PHP 8.4 | 不具合の修正は 2026年末まで。セキュリティの修正は 2028年末まで |
| PHP 8.5 | 不具合の修正は 2027年末まで。セキュリティの修正は 2029年末まで |
| PHP 8.6 | 決まりどおりなら、不具合の修正は 2028年末まで。セキュリティの修正は 2030年末まで |
※ PHP の公式サイトの予定です。8.6 は、まだ表に載っていないので、「リリースから2年は不具合の修正、その後2年はセキュリティの修正」という決まりから出した日付です。
8.2 のまま動いているサイトは、あと1か月半で、脆弱性が見つかっても直してもらえなくなります。
8.6 を待つより、まず 8.2 から上げるほうが先です。
このサイトの PHP は 8.4 です(8.4 に上げたときの話)。
念のため、今のコードを調べました。
8.6 は、使っているレンタルサーバーで選べるようになってから、手元の環境で確かめて上げる予定です。
新機能より、古いものの片づけのほうが多いバージョンです。
しかも、その一つひとつに「なぜやめるのか」がきちんと書いてあります。
理由が分かっていると、保守しているサイトを直すときも、お客様に説明するときも、ぐっと楽になります。
| 調べたもの | php-src の UPGRADING(PHP-8.6 ブランチ)PHP の RFCphp.net の Supported Versions |
|---|---|
| このサイトの確認 | PHP 8.4grep(非推奨の書き方の検索) |