Upgrade to Pro — share decks privately, control downloads, hide ads and more …

PHP8.2にバージョンアップして もっと型表現を豊かにしよう

PHP8.2にバージョンアップして もっと型表現を豊かにしよう

PHP8.2にバージョンアップしてもっと型表現を豊かにしよう
PHPカンファレンス沖縄2023 Akito.Tsukahara

PHP8.2からtrue/false型が実装されることはご存知でしょうか?
どのようにPHPの型表現がさらに豊かになったのか紹介させていただきます。

目次
・PHP8.2で新しくできること
・型表現を豊かにしてみよう
・バージョンアップしてみた
・まとめ

AkitoTsukahara

September 15, 2023
Tweet

More Decks by AkitoTsukahara

Other Decks in Programming

Transcript

  1. Copyright© M&Aクラウド PHP8.2で新しくできること 新機能💡 • true/false/nullが独⽴した型で利⽤可能に function alwaysTrue(): true {

    return true; } function alwaysFalse(): false { return true; } function alwaysNull(): null { return null; } function alwaysTrue(): bool { return true; } function alwaysFalse(): bool { return true; } function alwaysNull(): ?string //静的解析でエラー { return null; } PHP8.2~ ~PHP8.1
  2. Copyright© M&Aクラウド PHP8.2で新しくできること 新機能💡 • 選⾔標準形 (Disjunctive Normal Form) 型が使えるように

    public function bar((A&B)|null $entity) { return $entity; } public function bar(mixed $entity) { if ( (($entity instanceof A) && ($entity instanceof B)) || ($entity === null) ) { return $entity; } throw new Exception('Invalid entity'); } PHP8.2~ ~PHP8.1
  3. Copyright© M&Aクラウド PHP8.2で新しくできること 新機能💡 • クラスにreadonlyを指定することができるように readonly class OkinawaIsland {

    public function __construct( public string $name, public int $population, public int $area, ) { } } class OkinawaIsland { public function __construct( public readonly string $name, public readonly int $population, public readonly int $area, ) { } } PHP8.2~ ~PHP8.1
  4. Copyright© M&Aクラウド PHP8.2で新しくできること 新機能💡 • バックトレースにおけるセンシティブなパラメータの出⼒抑制ができる function getUser( $name, $email,

    #[SensitiveParameter] $password ) { throw new Exception('Error'); } getUser('taro', 'taro@example.com', 'taropass'); function getUser( $name, $email, #[SensitiveParameter] $password ) { throw new Exception('Error'); } getUser('taro', 'taro@example.com', 'taropass'); PHP8.2~ ~PHP8.1
  5. Copyright© M&Aクラウド 型表現を豊かにしてみよう その1 Nullオブジェクトパターンで使う👻 readonly class Speaker { public

    function __construct( private Name $name, private Email $email, private XAccountInterface $xAccount, ){} public function toArray(): array { return [ 'name' => $this->name->getValue(), 'email' => $this->email->getValue(), 'x_account' => $this->xAccount->isUndefined() ? null : $this->xAccount->getValue(), ]; } } Speaker.php
  6. Copyright© M&Aクラウド 型表現を豊かにしてみよう interface Undefinedable { public function isDefined(): bool;

    public function isUndefined(): bool; } その1 Nullオブジェクトパターンで使う👻 Undefinedable.php interface XAccountInterface extends Undefinedable { } XAccountInterface.php
  7. Copyright© M&Aクラウド class UndefinedXAccount extends XAccountInterface { public function isDefined():

    false { return false; } public function isUndefined(): true { return true; } } 型表現を豊かにしてみよう その1 Nullオブジェクトパターンで使う👻 class XAccount extends XAccountInterface { public function isDefined(): true { return true; } public function isUndefined(): false { return false; } } UndefinedXAccount.php XAccount.php
  8. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(引数)🧩 <?php interface A {} interface

    B {} class ClassAB implements A,B {} class TryDNFArgument { public function getAandB((A&B) | null $hoge): void { echo 'Call getAandB'; } } $tryDnfArg = new TryDNFArgument(); $tryDnfArg->getAandB(new ClassAB()); //Call getAandB A&B ⬅ ClassAB OK
  9. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(引数)🧩 <?php interface A {} interface

    B {} class ClassAB implements A,B {} interface C {} class ClassABC implements A,B,C {} class TryDNFArgument { public function getAandB((A&B) | null $data): void { echo 'Call getAandB'; } public function getAB(ClassAB | null $data): void { echo 'Call getAB'; } } <?php …… $tryDnfArg = new TryDNFArgument(); $tryDnfArg->getAandB(new ClassAB()); //Call getAandB  $tryDnfArg->getAB(new ClassAB()); //Call getAB $tryDnfArg->getAandB(new ClassABC()); //Call getAandB $tryDnfArg->getAB(new ClassABC()); //Fatal Error サンプルコード 引数の場合は、 A&B ⬅ ClassABC OK ClassAB ⬅ ClassABC Error
  10. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(引数)🧩 A 泳げる インターフェース B えらで呼吸

    インターフェース C 肺で呼吸 インターフェース A&B 泳げて 水中で呼吸できる C 魚類 ❌
  11. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(引数)🧩 A 泳げる B えらで呼吸 C

    肺で呼吸 A&B 泳げて 水中で呼吸 より広い型を受け入れられる 反変性 ※DNF型だから反変性を持つ訳ではなく、型表現の幅 が広がるという意味です。 「共変性と反変性」の完全サポートはPHP7.4から
  12. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(戻り値)🧩 <?php interface A {} interface

    B { function callB(): void; } class ClassAB implements A,B { function callB(): void { var_dump('callB'); } } class TryDNFReturnValue { public function getAandB(): (A&B)| null { return new ClassAB(); } } <?php …… $tryDnfRV = new TryDNFReturnValue(); $tryDnfRV->getAandB()?->callB(); //CallB
  13. Copyright© M&Aクラウド <?php …… class TryDNFReturnValue { public function getAandB():

    (A&B)| null { return new ClassABC(); } } $tryDnfRV = new TryDNFReturnValue(); $tryDnfRV->getAandB()?->callB(); //CallB $tryDnfRV->getAandB()?->callC(); //CallC 型表現を豊かにしてみよう <?php interface B { function callB(): void; } interface C { function callC(): void; } class ClassABC implements A,B,C { function callB(): void { var_dump('callB'); } function callC(): void { var_dump('callC'); } } その2 DNF型で型パズルする(戻り値)🧩 ただしPHPStanではエラーになる。 Call to an undefined method A&B::callC(). サンプルコード
  14. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(戻り値)🧩 会場までの 行き方ガイド A&B&C&D A 飛行機

    インターフェース B モノレール インターフェース C バス インターフェース D 徒歩 インターフェース 羽田からの 案内が記載 ないちゃー
  15. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(戻り値)🧩 会場までの 行き方ガイド B&C&D A 飛行機

    インターフェース B モノレール インターフェース C バス インターフェース D 徒歩 インターフェース ❌ 羽田からの 案内は不要 うちなーんちゅ
  16. Copyright© M&Aクラウド 型表現を豊かにしてみよう その2 DNF型で型パズルする(戻り値)🧩 会場までの 行き方ガイド ❌ 受け入れる型を絞る 共変性

    ※DNF型だから共変性を持つ訳ではなく、型表現の幅 が広がるという意味です。 「共変性と反変性」の完全サポートはPHP7.4から
  17. Copyright© M&Aクラウド バージョンアップしてみた <?php function calcDay(int $timestamp, int $day){ date_default_timezone_set('Asia/Tokyo');

    $calcTimestamp = strtotime(date('Y-m-d H:i:s', $timestamp) . sprintf('+%s day', $day)); echo date('Y-m-d H:i:s',$calcTimestamp); } $phpカンファレンス沖縄 2023当日 = 1694790000; //'2023-09-16 00:00:00'; calcDay($phpカンファレンス沖縄 2023当日, -3); ここで問題です! • 以下の処理の実⾏結果はどうなる?(~PHP8.1) ~PHP8.1
  18. Copyright© M&Aクラウド バージョンアップしてみた <?php function calcDay(int $timestamp, int $day){ date_default_timezone_set('Asia/Tokyo');

    $calcTimestamp = strtotime(date('Y-m-d H:i:s', $timestamp) . sprintf('+%s day', $day)); echo date('Y-m-d H:i:s',$calcTimestamp); } $phpカンファレンス沖縄 2023当日 = 1694790000; //'2023-09-16 00:00:00'; calcDay($phpカンファレンス沖縄 2023当日, -3); 結果は... 2023-09-13 00:00:00 ~PHP8.1
  19. Copyright© M&Aクラウド バージョンアップしてみた <?php function calcDay(int $timestamp, int $day){ date_default_timezone_set('Asia/Tokyo');

    $calcTimestamp = strtotime(date('Y-m-d H:i:s', $timestamp) . sprintf('+%s day', $day)); echo date('Y-m-d H:i:s',$calcTimestamp); } $phpカンファレンス沖縄 2023当日 = 1694790000; //'2023-09-16 00:00:00'; calcDay($phpカンファレンス沖縄 2023当日, -3); さらにもう⼀問! • 以下の処理の実⾏結果はどうなる?(PHP8.2~) PHP8.2~
  20. Copyright© M&Aクラウド バージョンアップしてみた <?php function calcDay(int $timestamp, int $day){ date_default_timezone_set('Asia/Tokyo');

    $calcTimestamp = strtotime(date('Y-m-d H:i:s', $timestamp) . sprintf('+%s day', $day)); echo date('Y-m-d H:i:s',$calcTimestamp); } $phpカンファレンス沖縄 2023当日 = 1694790000; //'2023-09-16 00:00:00'; calcDay($phpカンファレンス沖縄 2023当日, -3); 結果は... 2023-09-19 00:00:00 PHP8.2~ サンプルコード
  21. Copyright© M&Aクラウド バージョンアップしてみた <?php function calcDay(string $timestamp, int $day){ date_default_timezone_set('Asia/Tokyo');

    $calcTimestamp = strtotime(date('Y-m-d H:i:s', $timestamp) . sprintf('+%s day', $day)); echo date('Y-m-d H:i:s',$calcTimestamp); } $phpカンファレンス沖縄 2023当日 = 1694790000; //'2023-09-16 00:00:00'; calcDay($phpカンファレンス沖縄 2023当日, -3); おやおや...🤔 PHP8.2~ +-3 day
  22. Copyright© M&Aクラウド まとめ • PHP8.2から新しく実装機能がたくさん • PHPのバージョンを上げて、型表現を豊かにしよう ◦ true/false/nullが独⽴した型で使える ◦

    選⾔標準形 (Disjunctive Normal Form) 型が使える • バージョンを上げる時には「下位互換性のない変更点」をチェック • もうすぐPHP8.3がリリースされる
  23. Copyright© M&Aクラウド 参考資料 • https://www.php.net/releases/8.2/ja.php • https://www.prime-strategy.co.jp/column/archives/column_5253 • https://qiita.com/rana_kualu/items/fc4b02e2daaf102aa92f •

    https://www.cyberer.net/2020/03/covariant-contravariant.html • https://www.php.net/manual/ja/language.oop5.variance.php • https://zukan.com/fish/internal2961