# ShowNote:【オンライン】PHPerによるPHPerのための「『PHP8』のニュースや記事を語り合う」TechCafe @ RAKUS 9月 ## イベントページはこちら https://rakus.connpass.com/event/187049/ ## PHP8の変更点まとめ - **[What's new in PHP 8](https://stitcher.io/blog/new-in-php-8)** ### 新機能(主なもの) - **[Union types](https://stitcher.io/blog/new-in-php-8#union-types-rfc)** - 変数、引数、戻り値に複数の型を指定できるようになる - ``private int|float $number;`` - ``public function foo(Foo|Bar $input): int|float;`` - こういった記法はTypeScriptなどでもみられる記述 - これまではIDEや静的解析ツールのためにPHPDocで表現されていたが、言語仕様に取り込まれることで、実行時にチェックが行われるようになった - RFCには「Because they are enforced, type information is less likely to become outdated or miss edge-cases.(タイプ情報が強制されるため、タイプ情報が古くなったり、エッジケースを見逃したりする可能性が低くなります。)」とある。 - 賛否が分かれるが、今まであいまいに記述されていたものを、``int|string``とか``A | null``、``A | false``のように明示化できるのは良い事では? - **[JIT](https://stitcher.io/blog/new-in-php-8#jit-rfc)** - PHPに実行時コンパイラ(Just-In-Time Compiler)の機能が追加 - 通常、PHPのコードは次のような動きをする - ``ソースコード → OPcode(中間言語)に変換→ ZendVMがネイティブコードに変換(解釈)してCPUが実行`` - これを高速化するための仕組みとして``OPcache``がある。 - ``ソースコード → OPcode(中間言語)に変換してキャッシュ`` - 次にリクエストが来た時、 - ``キャッシュされたOPcodeをZendVMがネイティブコードに変換してCPUが実行`` - JITはこのOPcache、の発展形で、JITがONの場合は次のようになる - ``ソースコード → OPCodeに変換 → ネイティブコードに変換してキャッシュ`` - 次にリクエストが来た時、 - ``キャッシュされたネイティコードを直接CPUが実行`` - 実行時にZendVMがOPcode解釈をする部分のオーバーヘッドがなくなるため、高速に実行できる - **ただし、Webアプリケーションにおけるオーバーヘッドの大半はI/O(DBアクセスなど)なので、大きな高速化は見込めないと思われる** - 高速に計算処理を行うなど、これまでC言語などで実装していた部分をPHPで実装できるようになるという「可能性」が主なモチベーション - C言語に比べるとPHPはメモリの管理などが簡単なので、C言語よりも安全に実装することができる - [PHP8.0.0α1がリリースされたのでさっそくJITの威力を体感する(した)](https://qiita.com/rana_kualu/items/73c346b3feadfa3a5b21) - 著者も「本当かよ???」と書くほどの結果が出たJITによる速度向上の記事 - [PHP 8: A Quick Look at JIT](https://derickrethans.nl/a-quick-look-at-jit.html) - プロットデータから近似曲線を求めるアルゴリズムでテストした例 - 1000回実行に8.8secかかっていた処理が4.2secに - **[The nullsafe operator](https://stitcher.io/blog/new-in-php-8#the-nullsafe-operator-rfc)** - オブジェクトのパラメータやメソッドにアクセスする際に、いちいちnullチェックの判定を書く必要がなくなる - [PHP Internals News: Episode 65: Null safe operator](https://derickrethans.nl/phpinternalsnews-65.html) - APIの返却値のように、ツリーのようなデータ構造を取得した時、従来はnullチェックのif文が多くなり、冗長で退屈 - 簡潔に記述できるようになることで、コードの理解がしやすくなる - ショートサーキットについて - ``$foo = $a?->b();`` - $aがnullの場合は``b()``は実行されない - ``$a?->b($c->d());`` - $aがnullの場合は``b()``は実行されない - ``$c->d()``も評価されない - ``$a->b($c?->d());`` - $cがnullの場合は、``d()``は実行されない - ``$a->d()``にnullが渡される - **[Named arguments](https://stitcher.io/blog/new-in-php-8#named-arguments-rfc)** - メソッドの引数に名前を付ける事ができるようになる - ``array_fill(start_index: 0, num: 100, value: 50);`` - 呼び出しを見れば引数の意味が一目瞭然(自己文書化されている) - 従来は、引数の順序で判断していたが、名前で判断できるようになる - デフォルト値をスキップすることも可能 - [デフォルト値をスキップする例](https://stitcher.io/blog/php-8-named-arguments#why-named-arguments?) - 特にコンストラクタなどはデフォルト値が多いことが多く、名前付き引数を用いることでシンプルに記述できるようになる - デフォルト値を引数に持つメソッドの機能改修も楽になる - 従来は、デフォルト引数の問題を回避するために、``$option``といった配列を用いることもあったが、配列では中に何が設定できるのか分からず、PHPDocなどで確認するしかなかった - **[Attributes](https://stitcher.io/blog/new-in-php-8#attributes-rfc)** - 従来、PHPDocなどに記述していたメタデータを**正式に言語仕様として記述できるようにした**もの - PHPUnitの例 - https://phpunit.readthedocs.io/ja/latest/annotations.html - ``@test``,``@after``,``@before``,``@dataProvider``など - PHPDocへの記述の仕方は特に制約がなく、ライブラリの製作者などがめいめいに決めていた - PHPDocはただの文字列でしかなく、その中からメタデータを抽出するのは、文字列の解析(正規表現など)にたよるしかなかった - [PHPUnitのアノテーション判定部分](https://github.com/sebastianbergmann/phpunit/blob/master/src/Util/Annotation/DocBlock.php) - コード中にメタデータを記述したいという要求は潜在的に多く、改めて言語仕様として採用されるに至った - 言語仕様で決まっているので、メタデータへのアクセス方法もちゃんと定義されている - ``$attributes = $reflectionFunction->getAttributes(\My\Attributes\SingleArgument::class);`` - **ちなみに** - Attributesの記法については提案時点で二転三転しており、記事によっては実際に採用された記法と異なる記述で紹介されている場合もあるので**注意** - 古い提案:``<<属性>>``. ``@@属性`` - 正式版:``#[属性]`` - PHPUnitも2022年には新しい記法に対応するかも、とのこと - https://twitter.com/s_bergmann/status/1257282186652323842 - **[Match expression](https://stitcher.io/blog/new-in-php-8#match-expression-rfc)** - ``switch``**文**とよく似た機能を持つ``match``**式**の導入 - 文:値を返さない、式:値を返す - switch文と比較すると、 - 簡潔に記述できる(break行不要、複数の条件をまとめて記述できる、**式**なので代入処理を記述するのは1か所だけ) - 条件の判定が**厳密なチェック**(===と同等) - ``default``漏れを防止できる(エラーになる) - **[PHP 8: Match or Switch?](https://stitcher.io/blog/php-8-match-or-switch)** - Match式かSwitch式、どちらを使いたいですか? - 単一行でシンプルな代入処理はmatch式を使い、そうでないものはswitchが良さそう? - [PHP Internals News: Episode 67: Match Expression](https://derickrethans.nl/phpinternalsnews-67.html) - **[Constructor property promotion](https://stitcher.io/blog/new-in-php-8#constructor-property-promotion-rfc)** - クラスのプロパティ定義・コンストラクタをシンプルに記述できるようになる - https://stitcher.io/blog/constructor-promotion-in-php-8 - VOやDTOなど、コンストラクタでの処理が引数で初期化するだけになりがちなシンプルなクラスの場合、コード量が減る - コードの視認性が上がるので良さそう - **[New ``mixed`` type](https://stitcher.io/blog/new-in-php-8#new-mixed-type-rfc)** - 特定の型ではなく、**何か分からないけど、何かの型である**ことを示す型 - 現在のPHPはほとんどの部分に型情報を明示的に宣言できるが、過去にはそうではなかった - RFCでは、``mixed``を敢えて指定することが、次のような用途で用いることができるとしている - **型のことは気にしているが、「まだ正確に記述していない」** ということを明示する - **正確に型を指定することができない** ことを明示する - **何か明確な意図で「型を縛っていない」** ことを明示する - ちなみにへーしゃでは、リファクタリング途中であることをマーキングする目的で使えるのでは、という意見が出ていました。RFCに記載されている一番目の用途ですね - 「何も考えてない」のと「考えた結果敢えてそうしている」のは大きく違い、実装者の意図をコードに残せるという意味で、悪くない変更かと思います - **[Throw expression](https://stitcher.io/blog/new-in-php-8#throw-expression-rfc)** - アロー関数や三項演算子、NULL合体演算子などの式しか許されない場所から例外を投げれるようにする - match式と一緒に使うと、特定の条件の場合に例外を投げる、といった処理もシンプルに記述できるようになる - などなど ### Breaking Changes(旧バージョンとの互換性の無い変更。主催の主観で重要そうなものをピックアップ) - ちなみに、PHP8が正式リリース後にマイグレーションガイドが作成されるはずなので、実際にバージョンアップされる際はそちらを参考されたし - PHP7.3 -> PHP7.4 - https://www.php.net/manual/ja/migration74.php - **[Consistent type errors](https://stitcher.io/blog/new-in-php-8#consistent-type-errors-rfc)** - ``strlen``などの組み込み関数に、不正な型の値を渡すと、**常にTypeError例外が発生する**ようになる変更 - 元々は、``declare(strict_types=1);``を指定した時のみ上記の動きになっていた - strict_typesを指定しない場合は、Warningと共にNULLが返っていただけ - **[Reclassified engine warnings](https://stitcher.io/blog/new-in-php-8#reclassified-engine-warnings-rfc)** - 様々な警告、エラーのレベル見直し - 今まではWarningやNoticeで済んでいたものが、エラー落ちするようになったりする - 一覧は下記RFC中に記載 - https://wiki.php.net/rfc/engine_warnings - ちょっとザワついたが、実際に実装されたものはRFCで採択されたものと異なっているようで、少し優しめの変更になっている…?(正式版リリースまでに変わるのかもしれない) - https://github.com/php/php-src/blob/master/UPGRADING#L105 - PHPコミュニティの**過去の負債を消し去ろうとする強い意志を感じる** ``` 現時点のUPGRAGDINGの翻訳 いくつかの警告がエラー例外に変換されました: *非オブジェクトのプロパティに書き込もうとしています。以前これ null、false、および空の文字列に対してstdClassオブジェクトを暗黙的に作成しました。 * PHP_INT_MAXキーが指定されている配列に要素を追加しようとしています はすでに使用されています。 *無効なタイプ(配列またはオブジェクト)を配列キーとして使用しようとした、または 文字列のオフセット。 *スカラー値の配列インデックスに書き込もうとしています。 *非アレイ/トラバーサブルをアンパックしようとしています。 多くの通知が警告に変換されました: *未定義の変数を読み取ろうとしています。 *未定義のプロパティを読み取ろうとしています。 *未定義の配列キーを読み取ろうとしています。 *非オブジェクトのプロパティを読み取ろうとしています。 *非配列の配列インデックスにアクセスしようとしています。 *配列を文字列に変換しようとしています。 *リソースを配列キーとして使用しようとしています。 * null、ブール値、または浮動小数点数を文字列オフセットとして使用しようとしています。 *範囲外の文字列オフセットを読み取ろうとしています。 *空の文字列を文字列オフセットに割り当てようとしています。 RFC:https://wiki.php.net/rfc/engine_warnings ``` - **[The @ operator no longer silences fatal errors](https://stitcher.io/blog/new-in-php-8#reclassified-engine-warnings-rfc)** - エラー制御演算子``@``が、Fatalエラーを抑制しなくなる - 古いライブラリやソースコードなどで``@``でエラーを握りつぶしている場合があるが、通用しなくなるよ、ということ - PHPコミュニティの**過去の負債を消し去ろうとする強い意志を感じる** - **[Default error reporting level](https://stitcher.io/blog/new-in-php-8#default-error-reporting-level)** - デフォルトのエラーレベルが - ``E_ALL & ~E_NOTICE & ~E_STRICT & ~E_DEPRECATED``(通知や非互換性、非推奨などを除く) - や - ``E_ALL & ~E_NOTICE & ~E_STRICT``(注意や非互換性を除く) - ではなく、 - ``E_ALL``(全てのエラーを出力する) - になる - PHPコミュニティの**過去の負債を消し去ろうとする強い意志を感じる** - **[Saner numeric strings](https://stitcher.io/blog/new-in-php-8#saner-numeric-strings-rfc)** - 数値文字列(``"123  "``や``"123abc"``など)に対する仕様に奇妙な動きや不整合があり、それを見直した - 分かりやすいものだけピックアップすると - int型の引数を受け取るメソッドに対して``"123abc"``を渡した時… - PHP7.4以前:int(123)として動く - PHP8.0以降:TypeError - ``in_numeric``に対して``"123  "``を渡すと… - PHP7.4以前:false - PHP8.0以降:true - ``"123" == "123  "``が… - PHP7.4以前:false - PHP8.0以降:true - ブラウザからのリクエスパラメータを処理する部分などで影響が出る可能性がある(数値文字列を受け取るので) - **[Saner string to number comparisons](https://stitcher.io/blog/new-in-php-8#saner-string-to-number-comparisons-rfc)** - こちらは、数値文字列を緩い比較演算子(``==``)を使用した場合の比較結果に関する仕様の見直し - ``==``だけでなく、``in_array``やswitch文でも同様の比較が行われる |比較 | 7.4以前 | 8.0| |--- | --- | ---| |0 == "0" | TRUE | TRUE| |0 == "0.0" | TRUE | TRUE| |0 == "foo" | TRUE | FALSE| |0 == "" | TRUE | FALSE| |42 == "   42" | TRUE | TRUE| |42 == "42foo" | TRUE | FALSE| - **[Fatal error for incompatible method signatures](https://stitcher.io/blog/new-in-php-8#fatal-error-for-incompatible-method-signatures-rfc)** - 継承元と異なるシグネチャで定義されたメソッドがある場合にエラーになるようになった - PHP7.4以前は、Warningが発生するだけだった ## PHP8関連その他 - **PHP8をとりあえず触ってみたい方はこちら** - 各バージョンのPHP実行結果をみることができるサイト - https://3v4l.org/ - [Testing PHP 8 With Docker](https://www.colinodell.com/blog/202008/testing-php-8-with-docker) - [オフィシャルのDockerイメージ](https://github.com/docker-library/docs/blob/master/php/README.md#supported-tags-and-respective-dockerfile-links)がすぐに公開されるのでこちらを使うのもアリ - [Microsoftが「PHP」サポートを縮小 ~「PHP 8.0」バイナリは公式提供せず](https://forest.watch.impress.co.jp/docs/news/1264900.html)** - MicrosoftによるPHPの公式サポートはPHP7.4までとなり、PHP8.0からはサポートしなくなる。 - 今後はWindowsでのPHP開発はWSL2に移行していくと思われる - [Steps to Install Apache, MySQL and PHP in WSL 2 -Windows 10](https://www.how2shout.com/how-to/steps-to-install-apache-mysql-and-php-in-wsl-2-windows-10.html) - ちなみにWSL2ではDockerも動くので、Dockerイメージ使うのも一手 ## PHPWeekly ``` メルマガ登録はこちら http://phpweekly.com/ ``` ### 8/13 - [Why Startups Should Prefer PHP for Web Development](https://www.etatvasoft.com/blog/php-for-start-ups/) - PHPで開発することについて勇気づけられる記事 - [How to Switch from YAML/XML Configs to PHP Today with Migrify](https://tomasvotruba.com/blog/2020/07/27/how-to-switch-from-yaml-xml-configs-to-php-today-with-migrify/) - YAML の設定ファイルから脱却する最適解 - [Legacy to Laravel: How to Modernise an Aging PHP Application](https://tighten.co/blog/converting-a-legacy-app-to-laravel/) - レガシーシステムをLaravel に乗せ換えるためのベストプラクティス ### 8/20 - [From PHP Code to Static Analysis](https://www.exakat.io/from-php-code-to-static-analysis/) - PHP コードから静的分析までを解説している - しっかり読み込みたい - [Tools for PHP Development — Local Dev Site Setup](https://blog.fortrabbit.com/tools-for-php-development-local-dev-site-setup) - ローカルでPHPの環境を作成する際の様々な方法 - 聞いたことがないものもあったので深堀したい ### 8/27 - [Manager's Guide to PHP Testing](https://www.zend.com/blog/php-testing) - PHPでのテスト方法について - PHPでできるテスト手法について一覧化されており一見の価値ありかと - [4 Ways to Make Your Nette Project More Readable](https://tomasvotruba.com/blog/2020/08/10/4-ways-to-make-your-nette-project-more-readable/) - PHPコードの可読性を向上するためのテクニック - IDEの補完機能をフル活用するためのテクニック - rector というツールがよく登場している ### 9/10 - [Steps to Install Apache, MySQL and PHP in WSL 2 -Windows 10](https://www.how2shout.com/how-to/steps-to-install-apache-mysql-and-php-in-wsl-2-windows-10.html) - WSL2でPHP環境構築 <!-- 宣伝用:ゲスト参加者の皆さんの紹介 --> <!-- 白柳さんのYoutubeチャンネル https://www.youtube.com/channel/UCv1AIkCCrRB_Tcz_1ZgSoFg/videos --> <!-- endoさんのブログ https://www.fendo181.me/entry/phperkaigi-2019 -->