+-----------------------------------------------------------------------------+
| Typesafe Enum |
+-----------------------------------------------------------------------------+
- Synopsis
- Requirements
- Files
- Simple Usage: Generation
- Extended Usage: Methods
- Extended Usage: Configuration
- Extended Usage: Manual Definition
- Performance
Synopsis
--------
This package is an implementation of the Typesafe Enum Pattern known from JAVA
before it had its own Enum type. The Enum class can be used as base class to
implement typesafe enumerations easily in PHP and also to generate them
automatically.
If you are not familiar with the pattern, I recommend reading this explanation
of the JAVA pattern:
http://java.sun.com/developer/Books/shiftintojava/page1.html#replaceenums
Requirements
------------
The package requires PHP 5.2.6 or later.
It depends on the following functionality from PHP > 5.0:
5.2.5: debug_backtrace() parameter in Enum::define() and Enum::___get()
5.2.0: recursive mkdir in Enum::___writeToCache()
5.1.0: InvalidArgumentException from SPL in Enum::define() and Enum::valuesOf()
5.1.0: LOCK_EX flag in Enum::___writeToCache()
5.1.0: array_intersect_key in array_iunique
5.0.3: is_subclass_of in define_once and valuesOf
If you remove the respective optional parameters from debug_backtrace and mkdir
and don't set Enum::$cacheReUsePackagePath, the package works fine on PHP 5.1.0
Workarounds to get the package running on PHP 5.0 should also be possible but
are not recommended.
Files
-----
typesafeenum.lib.php - library loader, include this file to use the package
Enum.php - Enum base class and generator
cache/ - empty directory where the cached class files go. Must be writable!
example/example.php - Example to demonstrate simple usage
test/EnumTest.php - PHPUnit test case
test/EnumBenchmark.php - Benchmark class
test/run_benchmark.php - The script that I used for performance tests
license.txt - BSD License
readme.txt - the file you are reading right now
Simple Usage: Generation
-----
Typical usage of the generator:
Enum::define('MyEnum', 'Value1', 'Value2', 'Value3', 'Value4');
doSomething(MyEnum::Value1());
function doSomething(MyEnum $myenum) {
echo (string) $myEnum;
switch ($myenum) {
case MyEnum::Value1():
// do something for Value1
break;
case MyEnum::Value2():
// do something for Value2
break;
case MyEnum::Value3():
// do something for Value3
break;
case MyEnum::Value4():
// do something for Value4
break;
}
}
You can configure the behaviour of the generator with class variables of Enum,
the most important one is $cacheEnabled. It is true by default but you may want
to turn caching off, so that eval() will be used with the generated code
instead of cached files.
Enum::$cacheEnabled = false;
Extended Usage: Methods
-----
Besides define() there are two other public static methods in Enum:
define_once(string $enumName, string $value1, string $value2, ... )
define_once works exactly like define but does nothing if the given Enumeration
already is defined, similar to include_once and require_once.
valuesOf(string $enumName)
valuesOf returns all values (instances) of the given enumeration class.
Extended Usage: Configuration
-----
The caching can be configured with the following class variables:
bool $checkCache: Check if cached files are outdated (you may want to disable
this in productive environment). Defaults to true
string $cacheDir: Where the generated files should be stored (path relative to
this file). Defaults to 'cache'
bool $cacheReUsePackagePath: If package path should be mapped to cache dir
Useful if the same Enum names can occur in different packages. Defaults to
false. Example:
// in package1/subpackage/class.php:
Enum::$cacheReUsePackagePath = true;
Enum::define('MyEnum', 'FOO', 'BAR');
// in package2/otherclass.php:
Enum::$cacheReUsePackagePath = true;
Enum::define('MyEnum', 'MOO', 'NARF');
Now there will be two separate cached files:
- cache/package1/subpackage/MyEnum.php
- cache/package2/MyEnum.php
Of course both packages cannot be used simultaneous since we don't have
namespaces here.
string $cachePackageRoot: Package root (necessary for $cacheReUsePackagePath).
Defines from where the path should be reused.
Extended Usage: Manual Definition
-----
There are several scenarios where generating Enum classes with Enum::define()
is not sufficient:
- If you are using many Enum classes and need maximum performance (see next
section)
- If your system does not allow creation of files or eval()
- If you want to use the Enum classes in a more flexible way (i.e.
implementing a Comparable interface)
In these cases you can easily define them yourself like that:
final class MyEnum extends Enum
{
public static final function VALUE1() {
return self::___get('MyEnum', 'VALUE1');
}
public static final function VALUE2() {
return self::___get('MyEnum', 'VALUE2');
}
public static final function VALUE3() {
return self::___get('MyEnum', 'VALUE3');
}
}
The parameters of ___get may be omitted, then the calling class and method will
be determined automatically. If you add own functionality you can get the value
of the current instance with
(string)$this
or
parent::__tostring()
Performance
-----
Usually you should not worry about performance issues with the generator except
you define really many Enums in a time-critical environment. Then you may
consider resorting to manual definition.
To decide if caching is the right choice you can test the speed on your system
by running test/run_benchmark.php - you may want to change the first lines
beforehand to determine the number of defined Enum classes.
Note that depending on the filesystem caching does not necessary give an
advantage, so the decision may be based on other factors. |