PHP 8: 前と後

in Vlog

(jp) =

PHP 8 がリリースされるまであと数か月しかありませんが、正直なところ、優れた機能がたくさんあります。 この投稿では、PHP 8 が自分のコードに与える実際の影響を共有したいと思います。

# 属性を持つイベント サブスクライバー

属性を乱用しないように努めますが、イベント リスナーの構成は、私が広範囲に使用する注釈の例だと思います。

私が最近イベント ソース システムに取り組んでいることはご存知かもしれませんが、イベントの構成を行う必要がたくさんあることをお伝えできます。 たとえば、この単純なプロジェクターを見てください。



class CartsProjector implements Projector

    use ProjectsEvents;

    protected array $handlesEvents = [
        CartStartedEvent::class => 'onCartStarted',
        CartItemAddedEvent::class => 'onCartItemAdded',
        CartItemRemovedEvent::class => 'onCartItemRemoved',
        CartExpiredEvent::class => 'onCartExpired',
        CartCheckedOutEvent::class => 'onCartCheckedOut',
        CouponAddedToCartItemEvent::class => 'onCouponAddedToCartItem',
    ];

    public function onCartStarted(CartStartedEvent $event): void
      

    public function onCartItemAdded(CartItemAddedEvent $event): void
      

    public function onCartItemRemoved(CartItemRemovedEvent $event): void
      

    public function onCartCheckedOut(CartCheckedOutEvent $event): void
      

    public function onCartExpired(CartExpiredEvent $event): void
      

    public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
      

PHP 7.4

属性によって得られるメリットは 2 つあります。

  • イベント リスナーの構成とハンドラーがまとめられているため、リスナーが正しく構成されているかどうかを確認するためにファイルの先頭までスクロールする必要はありません。
  • もうメソッド名を文字列として書いたり管理したりする必要はありません。IDE はそれらをオートコンプリートできず、タイプミスの静的分析はなく、メソッドの名前変更は機能しません。

幸いなことに、PHP 8 はこれらの問題を解決します。

class CartsProjector implements Projector

    use ProjectsEvents;

    
    public function onCartStarted(CartStartedEvent $event): void
      

    
    public function onCartItemAdded(CartItemAddedEvent $event): void
      

    
    public function onCartItemRemoved(CartItemRemovedEvent $event): void
      

    
    public function onCartCheckedOut(CartCheckedOutEvent $event): void
      

    
    public function onCartExpired(CartExpiredEvent $event): void
      

    
    public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
      

PHP8

# doc ブロックの代わりに静的

小さいものですが、これは日々の影響があります。 静的な戻り値の型とジェネリックという 2 つの理由から、まだ doc ブロックが必要であることがよくあります。 後者の問題はまだ解決できていませんが、幸運にも最初の問題は PHP 8 で解決されるでしょう!

これを PHP 7.4 で書くと、次のようになります。


public static function new()

    return new static();

PHP 7.4

私は今書くことができるでしょう:

public static function new(): static

    return new static();

PHP8

私のブログを読めば、PHP の型システムをデータ転送オブジェクトと組み合わせて使用​​する方法について、かなりの量の記事を書いたことをご存知でしょう。 当然のことながら、私は自分のコードで多くの DTO を使用しているので、これを書き直すことができて、私がどれほど幸せか想像できるでしょう。

class CustomerData extends DataTransferObject

    public string $name;

    public string $email;

    public int $age;
    
    public static function fromRequest(
        CustomerRequest $request
    ): self 
        return new self([
            'name' => $request->get('name'),
            'email' => $request->get('email'),
            'age' => $request->get('age'),
        ]);
    


$data = CustomerData::fromRequest($customerRequest);

PHP 7.4

このように:

class CustomerData

    public function __construct(
        public string $name,
        public string $email,
        public int $age,
    ) 


$data = new CustomerData(...$customerRequest->validated());

PHP8

コンストラクタ プロパティの昇格と名前付き引数の両方の使用に注意してください。 はい、名前付き配列とスプレッド演算子を使用して渡すことができます!

# 列挙型と一致式

いくつかのメソッドを含む列挙型を使用していて、列挙型の値に基づいて異なる結果が得られることがありますか?


class InvoiceState extends Enum

    private const PENDING = 'pending';
    private const PAID = 'paid';

    public function getColour(): string
    
        return [
            self::PENDING => 'orange',
            self::PAID => 'green',
        ][$this->value] ?? 'gray';   
    

PHP 7.4

より複雑な条件の場合は、状態パターンを使用したほうがよいと思いますが、列挙型で十分な場合もあります。 この奇妙な配列構文は、すでにより冗長な条件の省略形です。


class InvoiceState extends Enum

    private const PENDING = 'pending';
    private const PAID = 'paid';

    public function getColour(): string
    
        if ($this->value === self::PENDING) 
            return 'orange';
        
    
        if ($this->value === self::PAID) 
            return 'green'
        

        return 'gray';
    

PHP 7.4 — 代替

しかし、PHP 8 では、 match 代わりに表現!


class InvoiceState extends Enum

    private const PENDING = 'pending';
    private const PAID = 'paid';

    public function getColour(): string
    
        return match ($this->value) 
            self::PENDING => 'orange',
            self::PAID => 'green',
            default => 'gray',
        ;
    

PHP8

tpyoに気づきましたか? PR を送信して修正することができます。 このブログの最新情報を知りたい場合は、私をフォローしてください。 ツイッター または私のニュースレターを購読してください:

# doc ブロックの代わりにユニオン型

私が言及したとき、 static 前に戻り値の型を説明しましたが、docblock の型ヒントが必要な別の使用例を忘れていました: ユニオン型です。 少なくとも、PHP 8 がネイティブにサポートしているため、以前は必須でした。


public function sanitize($input): string;

PHP 7.4

public function sanitize(string|int $input): string;

PHP8

# スロー式

PHP 8 より前では、 throw つまり、次のように明示的なチェックを行う必要があります。

public function (array $input): void

    if (! isset($input['bar'])) 
        throw BarIsMissing::new();
    
    
    $bar = $input['bar'];

    

PHP 7.4

PHP8では、 throw は式になっています。つまり、次のように使用できます。

public function (array $input): void

    $bar = $input['bar'] ?? throw BarIsMissing::new();

    

PHP8

# nullsafe 演算子

null 合体演算子に精通している場合は、その欠点に既に精通しています: メソッド呼び出しでは機能しません。 代わりに、中間チェックが必要です。 optional 一部のフレームワークによって提供されるヘルパー:

$startDate = $booking->getStartDate();

$dateAsString = $startDate ? $startDate->asDateTimeString() : null;

PHP 7.4

nullsafe 演算子の追加により、メソッドで null 合体のような動作を行うことができるようになりました!

$dateAsString = $booking->getStartDate()?->asDateTimeString();

PHP8

PHP 8 のお気に入りの機能は何ですか? 経由でお知らせください ツイッター または電子メールで!

//platform.twitter.com/widgets.js

関連記事

前の投稿
Diablo Immortal Terror’s Tide アップデートがゲームのメインストーリーを継続
次の投稿
壮大な戦い: 史上最大のライオン vs. 最大のトラ