• This repository has been archived on 08/Jul/2023
  • Stars
    star
    147
  • Rank 251,275 (Top 5 %)
  • Language
    PHP
  • License
    MIT License
  • Created over 12 years ago
  • Updated over 1 year ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

An enumeration implementation for PHP.

No longer maintained

This package is no longer maintained. See this statement for more info.

Enumeration

An enumeration implementation for PHP.

Current version image Current build status image Current coverage status image

Installation

What is an Enumeration?

In terms of software development, an enumeration (or "enumerated type") is essentially a fixed set of values. These values are called "members" or "elements".

An enumeration is used in circumstances where it is desirable to allow an argument to be only one of a particular set of values, and where anything else is considered invalid.

A basic example

Enumeration can be used like C++ enumerated types. Here is an example, representing a set of HTTP request methods:

use Eloquent\Enumeration\AbstractEnumeration;

final class HttpRequestMethod extends AbstractEnumeration
{
    const OPTIONS = 'OPTIONS';
    const GET = 'GET';
    const HEAD = 'HEAD';
    const POST = 'POST';
    const PUT = 'PUT';
    const DELETE = 'DELETE';
    const TRACE = 'TRACE';
    const CONNECT = 'CONNECT';
}

This class can now be used in a type hint to easily accept any valid HTTP request method:

function handleHttpRequest(HttpRequestMethod $method, $url, $body = null)
{
    // handle request...
}

Accessing enumeration members

Members are accessed by static method calls, like so:

handleHttpRequest(HttpRequestMethod::GET(), 'http://example.org/');
handleHttpRequest(HttpRequestMethod::POST(), 'http://example.org/', 'foo=bar&baz=qux');

For each member of the enumeration, a single instance of the enumeration class is instantiated (that is, an instance of HttpRequestMethod in the above example). This means that strict comparison (===) can be used to determine which member has been passed to a function:

function handleHttpRequest(HttpRequestMethod $method, $url, $body = null)
{
    if ($method === HttpRequestMethod::POST()) {
        // handle POST requests...
    } else {
        // handle other requests...
    }
}

Java-style enumerations

Java's enum types have slightly more functionality than C++ enumerated types. They can have additional properties and/or methods, and are really just a specialised kind of class where there are a fixed set of instances.

This is sometimes called the Multiton pattern, and in fact, all enumerations in this implementation are Multitons. The AbstractEnumeration class simply defines its members based upon class constants.

Here is an example borrowed from the Java documentation for its enum types. The following multiton describes all of the planets in our solar system, including their masses and radii:

use Eloquent\Enumeration\AbstractMultiton;

final class Planet extends AbstractMultiton
{
    /**
     * Universal gravitational constant.
     *
     * @var float
     */
    const G = 6.67300E-11;

    /**
     * @return float
     */
    public function surfaceGravity()
    {
        return self::G * $this->mass / ($this->radius * $this->radius);
    }

    /**
     * @param float $otherMass
     *
     * @return float
     */
    public function surfaceWeight($otherMass)
    {
        return $otherMass * $this->surfaceGravity();
    }

    protected static function initializeMembers()
    {
        new static('MERCURY', 3.302e23,  2.4397e6);
        new static('VENUS',   4.869e24,  6.0518e6);
        new static('EARTH',   5.9742e24, 6.37814e6);
        new static('MARS',    6.4191e23, 3.3972e6);
        new static('JUPITER', 1.8987e27, 7.1492e7);
        new static('SATURN',  5.6851e26, 6.0268e7);
        new static('URANUS',  8.6849e25, 2.5559e7);
        new static('NEPTUNE', 1.0244e26, 2.4764e7);
        // new static('PLUTO',   1.31e22,   1.180e6);
    }

    /**
     * @param string $key
     * @param float  $mass
     * @param float  $radius
     */
    protected function __construct($key, $mass, $radius)
    {
        parent::__construct($key);

        $this->mass = $mass;
        $this->radius = $radius;
    }

    private $mass;
    private $radius;
}

The above class can be used to take a known weight on earth (in any unit) and calculate the weight on all of the planets (in the same unit):

$earthWeight = 175;
$mass = $earthWeight / Planet::EARTH()->surfaceGravity();

foreach (Planet::members() as $planet) {
    echo sprintf(
        'Your weight on %s is %f' . PHP_EOL,
        $planet,
        $planet->surfaceWeight($mass)
    );
}

If the above script is executed, it will produce something like the following output:

Your weight on MERCURY is 66.107480
Your weight on VENUS is 158.422560
Your weight on EARTH is 175.000000
Your weight on MARS is 66.279359
Your weight on JUPITER is 442.677903
Your weight on SATURN is 186.513785
Your weight on URANUS is 158.424919
Your weight on NEPTUNE is 199.055584

Enumerations and class inheritance

When an enumeration is defined, the intent is usually to define a set of valid values that should not change, at least within the lifetime of a program's execution.

Since PHP has no in-built support for enumerations, this library implements them as regular PHP classes. Classes, however, allow for much more extensibility than is desirable in a true enumeration.

For example, a naive enumeration implementation might allow a developer to extend the HttpRequestMethod class from the examples above (assuming the final keyword is removed):

class CustomHttpMethod extends HttpRequestMethod
{
    const PATCH = 'PATCH';
}

The problem with this scenario is that all the code written to expect only the HTTP methods defined in HttpRequestMethod is now compromised. Anybody can extend HttpRequestMethod to add custom values, essentially voiding the reason for defining HttpRequestMethod in the first place.

This library provides built-in protection from these kinds of circumstances. Attempting to define an enumeration that extends another enumeration will result in an exception being thrown, unless the 'base' enumeration is abstract.

Abstract enumerations

Assuming that there really is a need to extend HttpRequestMethod, the way to go about it is to define an abstract base class, then extend this class to create the desired concrete enumerations:

use Eloquent\Enumeration\AbstractEnumeration;

abstract class AbstractHttpRequestMethod extends AbstractEnumeration
{
    const OPTIONS = 'OPTIONS';
    const GET = 'GET';
    const HEAD = 'HEAD';
    const POST = 'POST';
    const PUT = 'PUT';
    const DELETE = 'DELETE';
    const TRACE = 'TRACE';
    const CONNECT = 'CONNECT';
}

final class HttpRequestMethod extends AbstractHttpRequestMethod {}

final class CustomHttpMethod extends AbstractHttpRequestMethod
{
    const PATCH = 'PATCH';
}

In this way, when a developer uses a type hint for HttpRequestMethod, there is no chance they will ever receive the 'PATCH' method:

function handleHttpRequest(HttpRequestMethod $method, $url, $body = null)
{
    // only handles normal requests...
}

function handleCustomHttpRequest(
    CustomHttpRequestMethod $method,
    $url,
    $body = null
) {
    // handles normal requests, and custom requests...
}

More Repositories

1

phony

Mocks, stubs, and spies for PHP.
PHP
194
star
2

composer-npm-bridge

NPM integration for Composer packages.
PHP
78
star
3

pathogen

General-purpose path library for PHP.
PHP
76
star
4

otis

One-time password / multi-factor authentication library for PHP.
PHP
40
star
5

asplode

Drop-in exception-based error handling for PHP.
PHP
38
star
6

mooch

A simple Twitter OAuth proxy.
CoffeeScript
35
star
7

liberator

A proxy for circumventing PHP access modifier restrictions.
PHP
34
star
8

composer-config-reader

A light-weight component for reading Composer configuration files.
PHP
32
star
9

lockbox-php

Simple, strong encryption.
PHP
24
star
10

php-lcs

An implementation of the 'longest common subsequence' algorithm for PHP.
PHP
16
star
11

confetti

Streaming data transformation system for PHP.
PHP
15
star
12

pops

PHP object proxy system
PHP
15
star
13

dumpling

Diff-friendly mysqldump with an improved interface.
PHP
14
star
14

typhax

A flexible PHP type hinting syntax.
PHP
13
star
15

cosmos

A library for representing and manipulating PHP class names.
PHP
13
star
16

equality

A better strict comparison for PHP.
PHP
13
star
17

pbkdf2-compat

A compatibility library for the PHP 5.5 function hash_pbkdf2().
PHP
13
star
18

schemer

Generic schema validation library for PHP, based on JSON Schema.
PHP
12
star
19

liftoff

Open any file or URI using the default GUI application from within PHP.
PHP
12
star
20

github-release-action

A GitHub Action that creates GitHub Releases from your Git tags. Does what you probably wish GitHub would just do without the need to use GitHub Actions.
JavaScript
11
star
21

endec

Versatile encoding implementations for PHP.
PHP
9
star
22

fixie

YAML-based data fixtures.
PHP
8
star
23

lockbox-nodejs

Simple, strong encryption.
CoffeeScript
7
star
24

phony-peridot

Phony for Peridot.
PHP
6
star
25

phony-phpunit

Phony for PHPUnit.
PHP
6
star
26

blox

A parser for block comment documentation.
PHP
6
star
27

precis-js

A JavaScript implementation of RFC 7564 (The PRECIS Framework).
CoffeeScript
6
star
28

couchdb-builder

A tool for building CouchDB documents from flat files.
CoffeeScript
6
star
29

typhoon

Simple, flexible type-checking for PHP.
PHP
5
star
30

constance

PHP constants as enumerations.
PHP
5
star
31

phpstan-phony

PHPStan configuration for Phony.
PHP
5
star
32

phony-kahlan

Phony for Kahlan.
PHP
5
star
33

phpunit-extensions

Extensions for PHPUnit to provide additional functionality.
PHP
3
star
34

git-version-webpack-plugin

Pull Git version information into Webpack.
JavaScript
3
star
35

depict

A fast, recursion-safe, and succinct replacement for var_dump/var_export/print_r.
PHP
2
star
36

lockbox

Simple, strong encryption.
HTML
1
star
37

lockbox-java

Simple, strong encryption.
Java
1
star