Enumerated Constants in PHP with Namespaces

A few years ago, I wrote up an entry (Pseudo-enum in PHP) describing how to mimic enum types, like in C++.

C/C++:

#define ADMIN     0
#define MODERATOR 1
#define EDITOR    2

// ... same thing, but less typing...
enum { ADMIN, MODERATOR, EDITOR };

// ... regardless, now you can do ...
int myRole = ADMIN;


As mentioned in my older blog post, there’s no such native enum type or function in PHP, but you can make clever use of array_flip(), apc_define_constants() and apc_load_constants() to ultimately get the same effect.

I finished that old post wanting more, though, namely the ability to specify a namespace into which to define these enumerated constants. This was back in 2008, and I had no clue at the time how namespaces would be implemented in PHP. This has been a reality ever since PHP 5.3 came out, and so I decided to re-tool my previous approach.

To reiterate the problem: I want to specify nothing more than a set of strings, and end up with enumerated constants, with the option of putting them all in an arbitrary namespace to avoid name collisions.

BEHOLD! my_apc_enum() using PHP 5.4’s wonderful new short array syntax:

<?php
    /**
     * Try loading a set of constants from APC, otherwise
     * define them and store them into APC.
     */
    $key       = 'roles';
    $constants = ['ADMIN','MODERATOR','EDITOR'];

    my_apc_enum($key, $constants);

    echo "Admin: "     . ADMIN;     // Admin: 0
    echo "Moderator: " . MODERATOR; // Moderator: 1
    echo "Editor: "    . EDITOR;    // Editor: 2

    /**
     * OR you can put them all in a namespace
     */
    $key       = 'blogRoles';
    $constants = ['ADMIN','MODERATOR','EDITOR'];
    $namespace = 'blog';

    my_apc_enum($key, $constants, $namespace);

    echo "Admin: "     . blog\ADMIN;     // Admin: 0
    echo "Moderator: " . blog\MODERATOR; // Moderator: 1
    echo "Editor: "    . blog\EDITOR;    // Editor: 2

Another neat way to quickly see all constants you’ve defined, whether explicitly using define() one constant at a time, or using apc_define_constants(), is to use get_defined_constants():

<?php
    // array dereferencing! if you have PHP 5.4 ...
    print_r(get_defined_constants(true)['user']);

    // PHP 5.3 and below, you gotta do ...
    $constants = get_defined_constants(true);
    print_r($constants['user']);

Anyway, here’s how my_apc_enum() is implemented:

<?php
function my_apc_enum($key, $constants, $namespace = null) {

    // try loading the constants from APC
    if (!apc_load_constants($key)) {
    
        // was a namespace specified?
        if (!empty($namespace)) {
	    	
            // yep! prepend the namespace onto each constant name
            foreach ($constants as &$c) {
                $c = $namespace . '\\' . $c;
            }
        }

        // make APC define them all
        apc_define_constants($key, array_flip($constants));

        // APC cache miss :-(
        return false;
    }

    // APC cache hit :-)
    return true;
}