CodeBlanks Logo Icon CodeBlanks

Summary - Modern PHP

PHP course · Expert · Lesson 42/54

Build a modern state machine with readonly, enum, match and named arguments.

A state machine with modern PHP

This group covered PHP 8+ features: readonly properties, enum, the match expression, named arguments, Fiber and first-class callable (...).

Combine them to build immutable, type-safe models. Define an order's state with enum, wrap it in a readonly class and label it with match.

Named arguments make the call readable. In the type system, intersection types bind a parameter to multiple interfaces, e.g. function handle(HasId & HasName $x).

Exercise Order state machine

Define an int backed enum OrderStatus: Pending = 1, Shipped = 2, Delivered = 3.

Write a readonly class Order using constructor property promotion for int $id and OrderStatus $status. Write label(Order $o): string with match($o->status); return "Shipped" for Shipped.

The call below should print Shipped.

Show example solution
enum OrderStatus: int {
  case Pending = 1;
  case Shipped = 2;
  case Delivered = 3;
}

readonly class Order {
  public function __construct(
    public int $id,
    public OrderStatus $status
  ) {}
}

function label(Order $o): string {
  return match($o->status) {
    OrderStatus::Pending => "Pending",
    OrderStatus::Shipped => "Shipped",
    OrderStatus::Delivered => "Delivered",
  };
}

$o = new Order(id: 7, status: OrderStatus::Shipped);
echo label($o);

Test yourself

  1. Best representation for order state?

    • string
    • int constant
    • array
    • backed enum
    Show answer

    backed enum — Correct. A backed enum keeps state names and values together; it is type-safe and matches cleanly with switch/match.

  2. The match arm arrow

    $label = match($o->status) {
      OrderStatus::Shipped ____ "Shipped",
      default => "Unknown",
    };
    
    Show answer
    $label = match($o->status) {
      OrderStatus::Shipped => "Shipped",
      default => "Unknown",
    };
    
  3. Feature - role pairing

    readonly
    writable once
    enum
    type-safe constants
    match
    value-returning conditional
    ?->
    null-safe access

All lessons in Expert