enum_exists
Checks whether the given name is a defined enum, optionally triggering the autoloader.
enum_exists(string $enum, bool $autoload = true): bool- Added in PHP 8.1
Parameters
| Parameter | Type | Description |
|---|---|---|
$enum | string | The enum name, matched case-insensitively. Namespaced names must be fully qualified without a leading backslash. |
$autoloadoptional | bool= true | Whether to call the registered autoloaders if the enum is not already loaded. |
Return value
boolReturns true if enum is a defined enum, false otherwise.
Errors
Throws a TypeError if enum is not a string. A missing enum simply returns false.
enum_exists() is the enum-specific counterpart to class_exists(), added alongside enums in PHP 8.1. It returns true only when the name refers to an actual enum declaration, so it is the correct tool when a plain class would be wrong.
When to reach for it
Reach for it when a class-string arrives from outside your code — a route parameter, a config value, a serialized payload — and you intend to call ::from(), ::tryFrom() or ::cases() on it. Those static methods only exist on enums, so checking with class_exists() would let a regular class slip through and produce an Error at the call site. It is also useful in libraries that support both enum-backed and string-backed values and need to branch on which one they were handed.
Things that trip people up
- Enums are classes under the hood, so
class_exists()also returnstruefor them. The relationship is one-way:enum_exists()isfalsefor ordinary classes. - It tells you nothing about whether the enum is pure or backed. For that, check
is_subclass_of($name, BackedEnum::class). - To test a value rather than a name, use
$value instanceof UnitEnum.
Example
When to use it
- Validate an enum class-string that came from a route or config before calling ::from() on it
- Branch in a serializer between enum-backed and plain string fields
- Skip an optional feature when the enum it depends on ships in a newer package version
Frequently asked questions
What is the difference between enum_exists and class_exists?
enum_exists() returns true only for enum declarations, while class_exists() returns true for both classes and enums. Use enum_exists() when you are about to call enum-only methods such as cases(), from() or tryFrom().
Does enum_exists work with namespaced enums?
Yes, but you must pass the fully qualified name as a string without a leading backslash. Writing enum_exists(Suit::class) is the safest form because the compiler expands it for you.
How do I check whether a variable holds an enum instance?
Use $value instanceof UnitEnum for any enum, or $value instanceof BackedEnum for enums with scalar values. enum_exists() takes a name, not an instance.
More examples
Safely resolving a value through an unknown enum name
The two checks together are what make $enum::tryFrom() safe: enum_exists() rejects DateTime, and the BackedEnum check rejects pure enums, which have no from()/tryFrom() at all.
<?php
enum Status: string { case Open = 'open'; case Closed = 'closed'; }
function resolve(string $enum, string $value): string {
if (!enum_exists($enum) || !is_subclass_of($enum, BackedEnum::class)) {
return 'not a backed enum';
}
return $enum::tryFrom($value)?->name ?? 'unknown case';
}
echo resolve('Status', 'open'), "\n";
echo resolve('Status', 'archived'), "\n";
echo resolve('DateTime', 'open'), "\n";Telling pure and backed enums apart
Both names pass enum_exists(), but only Level implements BackedEnum. cases() works on either kind, which is why it is the safe way to enumerate values when you do not know the enum's flavour.
<?php
enum Direction { case Up; case Down; } // pure
enum Level: int { case Low = 1; case High = 2; } // backed
foreach (['Direction', 'Level'] as $name) {
$backed = enum_exists($name) && is_subclass_of($name, BackedEnum::class);
printf("%s: enum=%d backed=%d cases=%d\n",
$name, enum_exists($name), $backed, count($name::cases()));
}
Discussion