PHP 8:「前」および「後」コード(PHP 7.4との比較)





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
    { /* … */ }
}


PHP8のPHP7



属性には、次の2つの利点があります。



  • イベントリスナーとハンドラーを設定するためのコードは1つの場所にあり、リスナーが正しく設定されているかどうかを確認するために最初までスクロールする必要はありません。
  • メソッド名を文字列として書き込んだり操作したりすることを心配する必要がなくなりました(IDEがメソッド名を自動完了できない場合、タイプミスの静的分析がなく、メソッドの名前変更が機能しません)。


class CartsProjector implements Projector
{
    use ProjectsEvents;

    @@SubscribesTo(CartStartedEvent::class)
    public function onCartStarted(CartStartedEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartItemAddedEvent::class)
    public function onCartItemAdded(CartItemAddedEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartItemRemovedEvent::class)
    public function onCartItemRemoved(CartItemRemovedEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartCheckedOutEvent::class)
    public function onCartCheckedOut(CartCheckedOutEvent $event): void
    { /* … */ }

    @@SubscribesTo(CartExpiredEvent::class)
    public function onCartExpired(CartExpiredEvent $event): void
    { /* … */ }

    @@SubscribesTo(CouponAddedToCartItemEvent::class)
    public function onCouponAddedToCartItem(CouponAddedToCartItemEvent $event): void
    { /* … */ }
}


PHP 8



ドキュメントブロックの代わりに静的



これは大きな変化ではありませんが、私は毎日見ています。関数に静的リターンタイプがあることを指定する必要がある場合でも、docブロックが必要であることがよくあります。



PHP 7.4の場合、次のように書く必要がありました。



/**
 * @return static
 */
public static function new()
{
    return new static();
}


PHP 7.4では



、これで十分です。



public static function new(): static
{
    return new static();
}


PHP 8



DTO、プロパティと名前付き引数の受け渡し



PHPタイプのシステムとDTO(データ転送オブジェクトパターンの使用についてかなり書いてきました当然、私は自分のコードで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



名前付きパラメーターとしてコンストラクタープロパティを渡す方法の使用に注意してください。はい、名前付き配列とSpread演算子を使用して渡すことができます。



列挙と一致



列挙からの特定の値に応じて結果を返すいくつかのメソッドで列挙を使用していますか?



/**
 * @method static self PENDING()
 * @method static self PAID()
 */
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



より複雑な条件では、Stateパターンを使用する方が良いと思いますが、列挙で十分な場合もあります。この奇妙な配列構文は、すでにより厄介な条件式の省略形です。



/**
 * @method static self PENDING()
 * @method static self PAID()
 */
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を使用できます。



/**
 * @method static self PENDING()
 * @method static self PAID()
 */
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',
        };
}


PHP 8



ドキュメントブロックの代わりに結合



これは、静的リターンタイプについて前述したのと同じように機能します。



/**
 * @param string|int $input
 *
 * @return string 
 */
public function sanitize($input): string;


PHP 7.4



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


PHP 8



例外を投げる



以前は、式でthrowを使用できませんでした。つまり、たとえば、次のチェックを記述する必要がありました。



public function (array $input): void
{
    if (! isset($input['bar'])) {
        throw BarIsMissing::new();
    }
    
    $bar = $input['bar'];

    // …
}


PHP 7.4



PHP 8では、throwは式になりました。つまり、次のように使用できます。



public function (array $input): void
{
    $bar = $input['bar'] ?? throw BarIsMissing::new();

    // …
}


PHP 8



Nullsafe演算子



null合体演算子に精通している場合は、その欠点を認識しています。メソッド呼び出しでは機能しません。したがって、この目的に適した中間チェックまたはフレームワーク関数が必要になることがよくありました。



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


PHP 7.4



nullsafe演算子の導入により、この問題をはるかに簡単に解決できます。



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


PHP 8 PHP 8



のどのような革新が重要だと思いますか?






広告



プロジェクトを開発およびホストするためのサーバー各サーバーはDDoS攻撃から保護された500メガビットチャネルに接続されており、高速ローカルネットワークを使用することができます。ワンクリックで料金プランや変更が可能です。非常に便利なサーバーコントロールパネルとAPIを使用する機能。急いでチェックしてください!






All Articles