PHP 7.3

(Last Updated On: 2018年12月2日)

PHP 7.3が今月(2018/12)リリース予定です。新機能や機能変更は小振りですが、結構多くの追加/変更があります。ソースコード中のUPGRADINGに変更点は記載されています。ここでは独断と偏見で選んだ重要度が高い追加/変更を紹介します。 ※ PHP 7.3.0 RC6時点のUPGRADINGから紹介します。

記載していない変更の方が多いです。詳しくはリリース版のUPGRADINGを参照してください。

エラー処理の強化

バンドルされているモジュールのエラー処理はお世辞にも理想的と言える処理ではなかったモノがあります。これらのエラー処理が改善されました。エラーの発生の仕方やエラー発生後の動作が異なることになります。これでは困る事になるかも?と思うかも知れませんが、おかしな動作を起こすデータやコード、はそもそも問題の原因です。問題の原因を早く知ることができるようになります。

例えば、日付の変換関数などでエラーが起きた場合、エラー状態を知るにはerror_get_last()を呼び出す必要がありました。PHP 7.3からは”例外”を発生させます。このため、普通の例外処理でエラー状態の検出と対応ができるようになります。※ UPGRADINGでは「モードが”TH_THROW”の場合」と記述されています。これはPHP内部(=Cのコード)でエラー処理関数を呼び出す際のモードです。

BCMathのエラーは標準エラー出力に出力されるだけでしたが、PHPのエラーとして処理されるようになります。

json_decodeはエラー時にNULLを返しました。しかし、NULL自体もJSONの値としては”正しい”値であり、json_last_error()などで確認する必要がありました。PHP 7.3からJSON_THROW_ON_ERRORフラグにより例外を発生させることが可能です。

UPGRADINGには書ききれていない部分もあると思います。アップグレード時には注意が必要です。

Samesiteクッキーのサポート

今時のブラウザはクッキー属性としてsamesiteをサポートします。setcookieやセッションでsamesite属性がサポートされます。SamesiteはLaxとStrictが選べます。

Set-Cookie: CookieName=CookieValue; SameSite=Strict;

基本、Strictを利用する方が良いです。

全てのブラウザがSamesite属性をサポートするようになれば、samesite属性クッキーの有無でCSRF攻撃を判定することなどが可能になります。※ クライアント側仕様に頼る実装なので、強いCSRF対策とは言えませんが全てのブラウザがサポートすれば使えるモノになります。

※ PHP RFC: Same Site Cookie

文字列で指定すると間違えやすいので、定数やBoolで指定する方が良いのでは?と提案しましたが、文字列で指定します。タイポに注意しましょう!

関数引数に追加のコンマを許可

PHPの配列は最後の要素の後に “,”(コンマ)を許可していました。

$array = [
  1,
  2,
  3,
];

要素の追加や削除を行う場合、この仕様は便利です。

しかし、関数呼び出しの引数では追加の”,”は許可されていませんでした。PHP 7.3からは追加の”,”が許可されます。

unset(
    $somethingIDontNeedAnymore,
    $anotherOneToKill,
    $letsMakeThisEasy,
);

2013年にリジェクトされた時は反対する方の気が知れませんでした。幸いにも今回は通りました。配列構文で許可している追加の”,”が関数引数にも適用され、構文の整合性が取れるようになりました。

※ PHP RFC: Allow a trailing comma in function calls

list構文による参照変数の初期化

今時の言語はリスト要素(PHPの場合、配列とリストは同じ構造に保存される)の展開を容易に実行できます。PHPもlist構文か配列構文を使い展開できます。

$ php -a
Interactive shell

php > $a = [1,2];
php > [$x, $y] = $a;
php > var_dump($x, $y);
int(1)
int(2)

PHP 7.3からは参照変数も初期化できるようになります。

[$a, &$b] = $array;

「なぜ参照だと構文エラーになるんだ?」と思っていた開発者も多いと思います。PHP 7になって言語の内部処理が綺麗になったので、簡単に実装できるようになりました。あまり重要ではなく、気にする開発者が居なかったので実装までに少し時間が必要でした。

※ PHP RFC: list() Reference Assignment

heredoc/nowdoc構文の変更

heredoc/nowdocの文字列はインデントできませんでした。例えば以下のように、コードとのインデント位置を揃えて書き、余計なスペースを無視できませんでした。PHP 7.3からは以下のように書けます。

function something()
{
    stringManipulator(<<<END
       a
      b
     c
    END);
}

PHP 7.3未満で同等の文字列を生成するには、以下のように書く必要があります。

function something()
{
    stringManipulator(<<<END
   a
  b
 c
END
);
}

PHP RFC: Flexible Heredoc and Nowdoc Syntaxes

曖昧なcontinue文の禁止

実際に曖昧なcontinue文が禁止(構文エラー)になるのはPHP 8からです。PHP 7.3からWarningエラーになります。

continue文はループから抜ける為に利用する文ですが、switch文ではbreakと同等に動作していました。これはエラーになります。

        while ($foo) {
            switch ($bar) {
                case "baz":
                    continue;
                    // Warning: "continue" targeting switch is equivalent to
                                "break". Did you mean to use "continue 2"?
            }
        }

PHP 7.3未満でも文法的には曖昧ではなかったのですが「次のループ処理に移行する」つもりでcontinueを書いても、switch文内ではbreakの意味で動作していました。

本来、switchを抜けるにはbreakを用いるべきであり、上位ブロックのループから抜ける為にcontinueを使うはに”continue 2″などでなければなりません。PHP以外の言語では、switch文の中で”continue”を使うとPHPでいう所の”continue 2″の意味として動作します。この為、間違えやすい仕様であると長年指摘されてきました。

要するにPHP 7.3から”break”の代わりに”continue”は使えなくなります。

※ continue文は抜けるループのレベルを引数として受け付けます。”continue 3″とすると3つ上のレベルのループへ抜けられます。

より強力なパスワードハッシュをサポート

パスワードハッシュのデファクト標準はbcryptでしたが、最近はArgon2が標準になりつつあります。PHP 7.3からはArgon2がサポートされます。ただし、PHPソースコードにハッシュ関数ライブラリは組み込まれていないので、利用するには

--with-password-argon2[=dir]

でargon2ライブラリと一緒にビルドしたPHPが必要です。

Argon2が利用できる場合は積極的に利用すると良いです。

※ PHP RFC: Argon2 Password Hash Enhancements

文字列関数の変更

詳しく説明しませんが、文字列関数に変更があります。

  • mbregexに名前付きキャプチャーが追加。この為、動作が異なる。
  • pcreのライブラリがPCRE2に更新。この為、動作が異なる。
  • preg_quote()に”#”エスケープを追加される。
  • PHP 7.3では動作は変ならいが、文字列関数、strpos()などは、ord()でASCIIコードを指定できなくなる。将来”文字列ニードル”をサポートする為にASCIIコード利用が非推奨に変更。

といった変更があります。

正規表現(mbregex/pcre)の動作変更は解りづらいので注意が必要です。

投稿者: yohgaki