Originally published on php2rust.dev — part of the PHP to Rust course. View this lesson on the original site.

Rust enums can have variants with no data, tuple-like data, or struct-like named fields. PHP enums are simpler and backed by scalars; complex cases use classes or interfaces.

Use case

A common pattern is modeling everything the program might receive as one type, then handling each shape in a match. For example, a small UI or game loop might see events such as “quit,” “pointer moved,” “user typed text,” or “pick a new theme color”, each variant carries different data. Separately, a Color might be either exact RGB bytes or a named palette token from design settings. One enum per idea keeps queues, channels, and APIs simple: Vec<Message>, fn handle(ev: Message), and the compiler reminds you when a new variant appears.

Rust

// UI-style events: one type, many payload shapes.
enum Message {
    Quit,
    Move { x: i32, y: i32 },
    Write(String),
    ChangeColor(i32, i32, i32),
}

// Theme color: numeric RGB or a named swatch.
enum Color {
    Rgb(u8, u8, u8),
    Named(String),
}

fn show_accent(c: &Color) {
    match c {
        Color::Rgb(r, g, b) => println!("Accent (custom RGB): {}, {}, {}", r, g, b),
        Color::Named(s) => println!("Accent (palette): {}", s),
    }
}

fn handle_ui_event(ev: &Message) {
    match ev {
        Message::Quit => println!("Event: exit"),
        Message::Move { x, y } => println!("Event: pointer at ({}, {})", x, y),
        Message::Write(text) => println!("Event: typed {:?}", text),
        Message::ChangeColor(r, g, b) => println!("Event: theme RGB ({}, {}, {})", r, g, b),
    }
}

fn main() {
    let from_palette = Color::Named(String::from("Moss"));
    let from_picker = Color::Rgb(255, 0, 0);
    show_accent(&from_palette);
    show_accent(&from_picker);

    let frame_events = [
        Message::Move { x: 10, y: 20 },
        Message::Write(String::from("Hello")),
        Message::ChangeColor(0, 128, 255),
        Message::Quit,
    ];
    for ev in &frame_events {
        handle_ui_event(ev);
    }
}

PHP

<?php
// Same broad idea: one "kind" of thing (event, color choice) with different shapes per case.

// Simple enum
enum Color: string {
    case Red = 'red';
    case Named = 'named';
}

// For variants with data, use classes
abstract class Message {}
class Quit extends Message {}
class Move extends Message {
    public function __construct(
        public int $x,
        public int $y,
    ) {}
}
class WriteMessage extends Message {
    public function __construct(public string $text) {}
}

Comparison

  • Rust: Each variant can hold different types; a single enum type covers all cases (messages, events, config choices).
  • PHP: Backed enums map to scalars; variant-specific data usually modeled with classes.
  • Rust: Pattern matching handles all variants exhaustively.
  • PHP: match or switch for backed enums; instanceof or match for class hierarchies.

References

What's next

Next: Matching with enums.

From PHP to Rust — Rust Syntax and Functions