enum_exists

Checks whether the given name is a defined enum, optionally triggering the autoloader.

Signature
enum_exists(string $enum, bool $autoload = true): bool
  • Added in PHP 8.1

Parameters

ParameterTypeDescription
$enumstringThe enum name, matched case-insensitively. Namespaced names must be fully qualified without a leading backslash.
$autoloadoptionalbool= trueWhether 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 returns true for them. The relationship is one-way: enum_exists() is false for 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

Try it yourself
Loading editor…
Press Run to execute the code.

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.

Example · php
<?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.

Example · php
<?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

  • Be the first to comment on this lesson.