Enums (PHP 8.1)
Part of the Object Oriented Programming section of Coddy's PHP journey — lesson 59 of 91.
Before PHP 8.1, representing a fixed set of values like statuses or types meant using class constants or magic strings - both error-prone approaches. Enums (enumerations) provide a proper way to define a type that can only hold specific, predefined values.
Define an enum using the enum keyword:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name;
Output:
ActiveEnums can also have backed values - string or integer values associated with each case. This is useful when storing enums in databases or APIs:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value;
Output:
activeBacked enums provide a from() method to create an enum from its value, and tryFrom() which returns null instead of throwing an error for invalid values:
<?php
$status = Status::from('active'); // Returns Status::Active
$invalid = Status::tryFrom('unknown'); // Returns null
Enums can also contain methods, making them powerful for encapsulating related logic. They work seamlessly with type hints, ensuring your functions only accept valid values - no more checking if a string matches expected options.
Challenge
EasyLet's build an order management system that uses enums to represent order statuses in a type-safe way. Instead of relying on strings that could be misspelled or invalid, you'll create a backed enum that maps each status to a database-friendly value.
You'll organize your code across three files:
OrderStatus.php— Create a string-backed enum calledOrderStatuswith four cases:Pendingbacked by'pending'Processingbacked by'processing'Shippedbacked by'shipped'Deliveredbacked by'delivered'
label()that returns a human-readable description for each status:- Pending returns
"Awaiting confirmation" - Processing returns
"Being prepared" - Shipped returns
"On the way" - Delivered returns
"Order complete"
Order.php— Create anOrderclass that uses the enum. Include the OrderStatus file. The class should:- Accept an order ID (string) and an
OrderStatusin its constructor using constructor promotion - Have a method
getInfo()that returns"Order [id]: [status label]" - Have a method
getStatusValue()that returns the backed value of the status (useful for database storage)
- Accept an order ID (string) and an
main.php— Include the Order file. You'll receive two inputs: an order ID and a status string (like"shipped"). UsetryFrom()to safely convert the string input to anOrderStatusenum. If the status is valid, create anOrderand print two lines:- The result of
getInfo() - The result of
getStatusValue()
"Invalid status".- The result of
This challenge demonstrates how enums provide type safety — your Order class can only accept valid statuses, and the tryFrom() method lets you safely handle user input without risking invalid values.
Cheat sheet
Enums provide a type-safe way to define a fixed set of values. Define an enum using the enum keyword:
<?php
enum Status {
case Pending;
case Active;
case Completed;
}
$status = Status::Active;
echo $status->name; // Outputs: Active
Backed enums associate string or integer values with each case:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
case Completed = 'completed';
}
$status = Status::Active;
echo $status->value; // Outputs: active
Use from() to create an enum from its value, or tryFrom() which returns null for invalid values:
<?php
$status = Status::from('active'); // Returns Status::Active
$invalid = Status::tryFrom('unknown'); // Returns null
Enums can contain methods to encapsulate related logic:
<?php
enum Status: string {
case Pending = 'pending';
case Active = 'active';
public function label(): string {
return match($this) {
self::Pending => 'Awaiting',
self::Active => 'In Progress',
};
}
}
Try it yourself
<?php
require_once 'Order.php';
// Read input
$orderId = trim(fgets(STDIN));
$statusString = trim(fgets(STDIN));
// TODO: Use OrderStatus::tryFrom() to safely convert the status string to an enum
// tryFrom() returns null if the value is invalid
// TODO: If the status is valid, create an Order and print:
// - The result of getInfo()
// - The result of getStatusValue()
// TODO: If the status is invalid, print "Invalid status"
?>This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of OOP
External FilesIntroduction to OOPClasses vs ObjectsThe $this KeywordMethodsPropertiesConstructor (__construct)Destructor (__destruct)Recap - Simple Calculator4Inheritance
Basic InheritanceThe parent:: KeywordMethod OverridingThe final KeywordAbstract ClassesRecap - Employee Hierarchy7Encapsulation
Public, Protected, PrivateAccess Modifiers in DepthGetters and SettersInformation HidingConstructor Promotion (8.0)Recap - Student Records System10Advanced OOP Concepts
Composition vs InheritanceDependency InjectionAnonymous ClassesEnums (PHP 8.1)Fibers (PHP 8.1)Object Cloning Deep DiveGenerators & Iterators2Namespaces & Autoloading
Introduction to NamespacesThe use KeywordPSR-4 Autoloading StandardComposer AutoloaderRecap - Organized Project5Interfaces & Contracts
Introduction to InterfacesImplementing InterfacesMultiple Interface ImplementInterface vs Abstract ClassType Hinting with InterfacesRecap - Shape Calculator8Magic Methods
Magic Methods Introduction__toString & __debugInfo__get, __set, __isset, __unset__call & __callStatic__clone & Object Cloning__serialize & __unserializeRecap - Custom Collection11Type System & Error Handling
Type DeclarationsNullable TypesUnion & Intersection TypesException ClassesCustom Exception HierarchyTry, Catch, FinallyRecap - Form Validator14Project: Library Management
Project OverviewBook and User Classes3Class Properties
Instance vs Static PropertiesConstants in ClassesStatic Methods & PropertiesPrivate & Protected PropertiesReadonly Properties (PHP 8.1)Recap - Bank Account Manager6Polymorphism
Method Overriding RevisitedPolymorphism via InterfacesType Hinting & Union TypesLate Static BindingRecap - Payment Processor9Traits
Introduction to TraitsUsing Multiple TraitsTrait Conflict ResolutionAbstract Methods in TraitsTraits vs Inheritance12Design Patterns Part 1
Intro to Design PatternsSingleton PatternFactory PatternObserver PatternStrategy Pattern