PHP 8.3 enums are perfect for managing fixed sets of values like video categories, regions, and cache policies. Here's how I use them in TopVideoHub.
Why Enums?
Before enums, we used string constants:
// Before: fragile, no type safety
class Categories {
const MUSIC = 'music';
const GAMING = 'gaming';
const ENTERTAINMENT = 'entertainment';
}
function getVideos(string $category): array { /* ... */ }
getVideos('musci'); // Typo compiles fine, fails silently
With enums:
// After: type-safe, IDE support, exhaustive matching
enum Category: string {
case Music = 'music';
case Gaming = 'gaming';
case Entertainment = 'entertainment';
}
function getVideos(Category $category): array { /* ... */ }
getVideos(Category::Music); // Type-safe
Video Categories
YouTube has fixed category IDs. I map them to a PHP enum:
enum VideoCategory: int {
case FilmAnimation = 1;
case AutosVehicles = 2;
case Music = 10;
case PetsAnimals = 15;
case Sports = 17;
case ShortMovies = 18;
case TravelEvents = 19;
case Gaming = 20;
case Videoblogging = 21;
case PeopleBlogs = 22;
case Comedy = 23;
case Entertainment = 24;
case NewsPolitics = 25;
case HowtoStyle = 26;
case Education = 27;
case ScienceTech = 28;
case NonprofitsActivism = 29;
case Movies = 30;
case AnimeAnimation = 31;
case ActionAdventure = 32;
case Classics = 33;
case Documentary = 35;
case Shorts = 42;
public function label(): string {
return match($this) {
self::FilmAnimation => 'Film & Animation',
self::Music => 'Music',
self::Gaming => 'Gaming',
self::Entertainment => 'Entertainment',
self::NewsPolitics => 'News & Politics',
self::ScienceTech => 'Science & Tech',
self::HowtoStyle => 'How-to & Style',
self::Education => 'Education',
self::Comedy => 'Comedy',
self::Sports => 'Sports',
self::PeopleBlogs => 'People & Blogs',
default => $this->name,
};
}
public function slug(): string {
return strtolower(preg_replace('/[^a-z0-9]+/i', '-', $this->label()));
}
public function icon(): string {
return match($this) {
self::Music => 'music-note',
self::Gaming => 'gamepad',
self::Entertainment => 'star',
self::NewsPolitics => 'newspaper',
self::ScienceTech => 'flask',
self::Sports => 'trophy',
default => 'play-circle',
};
}
/**
* Categories displayed in the navigation bar.
*/
public static function navCategories(): array {
return [
self::Music,
self::Gaming,
self::Entertainment,
self::NewsPolitics,
self::ScienceTech,
self::Sports,
self::HowtoStyle,
self::Education,
self::Comedy,
self::PeopleBlogs,
];
}
}
Region Enum
enum Region: string {
case US = 'US';
case GB = 'GB';
case JP = 'JP';
case KR = 'KR';
case TW = 'TW';
case SG = 'SG';
case VN = 'VN';
case TH = 'TH';
case HK = 'HK';
public function label(): string {
return match($this) {
self::US => 'United States',
self::GB => 'United Kingdom',
self::JP => 'Japan',
self::KR => 'South Korea',
self::TW => 'Taiwan',
self::SG => 'Singapore',
self::VN => 'Vietnam',
self::TH => 'Thailand',
self::HK => 'Hong Kong',
};
}
public function flag(): string {
// Convert country code to flag emoji
$chars = str_split($this->value);
return implode('', array_map(
fn(string $c) => mb_chr(ord($c) - ord('A') + 0x1F1E6),
$chars
));
}
public function hreflang(): string {
return match($this) {
self::JP => 'ja',
self::KR => 'ko',
self::TW => 'zh-TW',
self::HK => 'zh-HK',
self::VN => 'vi',
self::TH => 'th',
default => 'en',
};
}
}
Using Enums in Practice
The best part about enums is exhaustive matching. If you add a new region, PHP tells you everywhere you need to handle it:
// This match is exhaustive — add a new Region case
// and PHP warns you about every unhandled match
function cronInterval(Region $region): string {
return match($region) {
Region::US, Region::GB => '*/2 * * * *',
Region::JP, Region::KR => '*/3 * * * *',
Region::TW, Region::SG, Region::HK => '*/4 * * * *',
Region::VN, Region::TH => '*/6 * * * *',
};
}
At TopVideoHub, enums eliminated an entire class of bugs — typos in region codes, invalid category IDs, and misconfigured cache policies. If you're on PHP 8.1+, there's no reason not to use them.
Typed Constants (PHP 8.3)
PHP 8.3 added typed constants, which complement enums nicely:
class CacheConfig {
const int HOME_TTL = 10800;
const int WATCH_TTL = 21600;
const int SEARCH_TTL = 600;
const int CATEGORY_TTL = 86400;
const string CACHE_DIR = 'data/pagecache';
}
These prevent accidentally assigning the wrong type to a constant. Small feature, real bugs prevented.
Top comments (0)