florianwolters / component-core-enum
The Typesafe Enum pattern as a PHP component.
Requires
- php: >=5.4
- florianwolters/component-core-comparable: 0.2.*
- florianwolters/component-core-debugprint: 0.2.*
- florianwolters/component-core-equality: 0.2.*
- florianwolters/component-core-immutable: 0.1.*
- florianwolters/component-core-stringutils: 0.3.*
- florianwolters/component-util-reflection: 0.2.*
- florianwolters/component-util-singleton: 0.3.*
This package is not auto-updated.
Last update: 2024-10-26 12:29:22 UTC
README
FlorianWolters\Component\Core\Enum is a simple-to-use PHP component that provides the Typesafe Enum pattern.
Table of Contents
- Introduction
- Motivation
- Features
- Requirements
- Usage
- Installation
- As A Dependency On Your Component
- Development Environment
- License
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 otherint
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()
andunserialize()
. - 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:
- Dynamic component tests (unit tests) implemented using PHPUnit.
- Static code analysis performed using the following tools:
- PHP_CodeSniffer: Style Checker
- PHP Mess Detector (PHPMD): Code Analyzer
- phpcpd: Copy/Paste Detector (CPD)
- phpdcd: Dead Code Detector (DCD)
- Installable via Composer or PEAR installer:
- Provides a Packagist package which can be installed using the dependency manager Composer.
- Provides a PEAR package which can be installed using the package manager PEAR installer.
- Click here for the PEAR channel.
- 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
- PHP >= 5.4
- florianwolters/component-core-comparable
- florianwolters/component-core-debugprint
- florianwolters/component-core-equality
- florianwolters/component-core-immutable
- florianwolters/component-util-reflection
- florianwolters/component-util-singleton
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.