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:
matchorswitchfor backed enums;instanceoformatchfor class hierarchies.
References
What's next
Next: Matching with enums.
From PHP to Rust — Rust Syntax and Functions