florianwolters/component-core-enum

The Typesafe Enum pattern as a PHP component.

v0.4.1 2013-06-29 12:42 UTC

This package is not auto-updated.

Last update: 2024-04-13 09:59:16 UTC


README

Build Status

FlorianWolters\Component\Core\Enum is a simple-to-use PHP component that provides the Typesafe Enum pattern.

Table of Contents

Introduction

The PHP scripting language is missing one important data type: The enumerated type.

Today, with version 5.4 of the PHP scripting language, there is still no linguistic support for enumerated types. It only exists a Request For Comments (RFC) from 2010-05-21) that suggests adding a enum language structure.

Many programming languages, e.g. Pascal, Modula-2, Modula-3, Ada, Haskell, C, C++ und C# have an enumerated type. Java, for example, implements the enumeration type via objects (see Java Tutorial and Java API documentation).

One can use the int Enum pattern to represent an enumerated type in PHP:

<?php
public const SEASON_WINTER = 0;
public const SEASON_SPRING = 1;
public const SEASON_SUMMER = 2;
public const SEASON_FALL = 3;

The int Enum pattern has many (severe) problems, such as:

  • Not typesafe - Since a season is just an int you can pass in any other int value where a season is required, or add two seasons together (which makes no sense).
  • No namespace - You must prefix constants of an int enum with a string (in this case SEASON_) to avoid collisions with other int enum types.
  • Brittleness - Because int enums are compile-time constants, they are compiled into clients that use them. If a new constant is added between two existing constants or the order is changed, clients must be recompiled. If they are not, they will still run, but their behavior will be undefined.
  • Printed values are uninformative - Because they are just ints, if you print one out all you get is a number, which tells you nothing about what it represents, or even what type it is.

It is possible to get around these problems by using the Typesafe Enum pattern (see Effective Java Item 21). This pattern has its own problems: It is quite verbose, hence error prone, and its enum constants cannot be used in switch statements.

(cf. Oracle. Enums)

Motivation

Since there is no enumerated type in PHP, I decided to create my own implementation.

My solution implements the Typesafe Enum pattern. The pattern has been adapted and abstracted for PHP. Because of that, my implementation doesn't have the problems of the original Typesafe Enum pattern (see Introduction above):

  • The enumeration constants can be used in switch statements (this is not possible in Java 1.5).
  • It is not as verbose as the original implementation (see Usage below), hence less error prone.

Features

  • The abstract enumeration base class implements the Typesafe Enum (see Effective Java Item 21) pattern.
  • Supports autocompletion within an Integrated Development Environment (IDE).
  • Supports functional enumerations. This means that one can use operations (method calls) on enumeration constants.
  • An enumeration class can extend another enumeration class, hence an enumeration hierarchy can be built.
  • The enumeration constants can be serialized/unserialized via the functions serialize() and unserialize().
  • An enumeration class can be placed in a namespace, hence naming collisions can be avoided.
  • Each enumeration constant is an object which is
    • a Singleton, more precisely a Multiton (see Design Patterns. Elements of Reusable Object-Oriented Software Item 3)
    • and an Immutable ValueObject. This means that each enumeration constant is represented by only one instance and the comparison is based on the name of the enumeration constant.
  • An enumeration constant cannot be instantiated via the new keyword.
  • An enumeration constant cannot be cloned via the magic __clone method.
  • Artifacts tested with both static and dynamic test procedures:
  • Installable via Composer or PEAR installer:
  • Provides a complete Application Programming Interface (API) documentation generated with the documentation generator ApiGen.
    • Click here for the current API documentation.
  • Follows the PSR-0 requirements for autoloader interoperability.
  • Follows the PSR-1 basic coding style guide.
  • Follows the PSR-2 coding style guide.
  • Follows the Semantic Versioning Specification (SemVer) 2.0.0-rc.1.

FlorianWolters\Component\Core\Enum does not (and will not) feature the following:

  • Generation of enumeration classes.
  • Support for PHP versions <= 5.4.

Requirements

Usage

The most important usage rule:

Always declare the method to retrieve the enumeration constant as final public static and write the name of the method in uppercase characters.

One should follow these best practices when using FlorianWolters\Component\Core\Enum:

  • Always declare an enumeration class as final, except the enumeration class should be extended by another enumeration class.
  • Always add a DocBlock tag @return with the name of the enumeration class to each method that retrieves an enumeration constant. This enables Autocompletion in the Integrated Development Environment (IDE).
  • Always add the suffix Enum to the name of a class which represents an enumeration type. This is analogical to the naming conventions for interfaces and abstract classes as described in PSR-2.

The following resources contain additional information:

  • Click here for the Wiki of FlorianWolters\Component\Core\Enum. The section Usage of the Wiki contains several documented source code examples.
  • Click here for the API documentation of FlorianWolters\Component\Core\Enum.

Installation

Local Installation

FlorianWolters\Component\Core\Enum should be installed using the dependency manager Composer. Composer can be installed with PHP.

php -r "eval('?>'.file_get_contents('http://getcomposer.org/installer'));"

This will just check a few PHP settings and then download composer.phar to your working directory. This file is the Composer binary. It is a PHAR (PHP archive), which is an archive format for PHP which can be run on the command line, amongst other things.

Next, run the install command to resolve and download dependencies:

php composer.phar install

System-Wide Installation

FlorianWolters\Component\Core\Enum should be installed using the PEAR installer. This installer is the PHP community's de-facto standard for installing PHP components.

pear channel-discover http://pear.florianwolters.de
pear install --alldeps fw/Enum

As A Dependency On Your Component

Composer

If you are creating a component that relies on FlorianWolters\Component\Core\Enum, please make sure that you add FlorianWolters\Component\Core\Enum to your component's composer.json file:

{
    "require": {
        "florianwolters/component-core-enum": "0.4.*"
    }
}

PEAR

If you are creating a component that relies on FlorianWolters\Component\Core\Enum, please make sure that you add FlorianWolters\Component\Core\Enum to your component's package.xml file:

<dependencies>
  <required>
    <package>
      <name>Enum</name>
      <channel>http://pear.florianwolters.de</channel>
      <min>0.4.0</min>
      <max>0.4.99</max>
    </package>
  </required>
</dependencies>

Development Environment

If you want to patch or enhance this component, you will need to create a suitable development environment. The easiest way to do that is to install phix4componentdev:

# phix4componentdev
pear channel-discover pear.phix-project.org
pear install phix/phix4componentdev

You can then clone the Git repository:

# PHP-Component-Core-Enum
git clone https://github.com/florianwolters/PHP-Component-Core-Enum

Then, install a local copy of this component's dependencies to complete the development environment:

# build vendor/ folder
phing build-vendor

To make life easier for you, common tasks (such as running unit tests, generating code review analytics, and creating the PEAR package) have been automated using phing. You'll find the automated steps inside the build.xml file that ships with the component.

Run the command phing in the component's top-level folder to see the full list of available automated tasks.

License

This program is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.

You should have received a copy of the GNU Lesser General Public License along with this program. If not, see http://gnu.org/licenses/lgpl.txt.