2017 © Pedro Peláez
 

library enums

Enums for PHP 5.4+

image

timetoogo/enums

Enums for PHP 5.4+

  • Sunday, April 20, 2014
  • by TimeToogo
  • Repository
  • 2 Watchers
  • 22 Stars
  • 5 Installations
  • PHP
  • 0 Dependents
  • 0 Suggesters
  • 1 Forks
  • 0 Open issues
  • 8 Versions
  • 0 % Grown

The README.md

Enums for PHP 5.4+

Installation

Add package to composer.json., (*1)

{
    "require": {
        "timetoogo/enums": "*"
    }
}

Or manually require {Path to Enum}/Loader.php, (*2)

Summary

  • An enum is a group of possible values: DayOfWeek
  • An an instance of an enum represents an underlying value: DayOfWeek::Thursday()->GetValue()
  • Two enum instances of the same type, representing the same value are identical: DayOfWeek::Thursday() === DayOfWeek::Thursday()
  • Enums are type safe: function SetDay(DayOfWeek $DayOfWeek)
  • Enums are extensible: DayOfWeek::Thursday()->GetTomorrow()
  • Enum values are serializable: DayOfWeek::Serialize(DayOfWeek::Thursday())
  • Enum values can be represented as a string: (string)DayOfWeek::Thursday()

An introduction

final class Boolean extends \Enum\Simple {

    public static function True() {
        return self::Representing('True');
    }

    public static function False() {
        return self::Representing('False');
    }
}

Congrats, we have successfully reimplemented the boolean using enums., (*3)

Lets test it out:, (*4)

var_export(Boolean::True() === Boolean::True()); //true
var_export(Boolean::True() === Boolean::False()); //false
var_export(Boolean::False() === Boolean::False()); //true

Great it works, now lets reimplement ! operator., (*5)

final class Boolean extends \Enum\Simple {

    public static function True() {
        return self::Representing('True');
    }

    public static function False() {
        return self::Representing('False');
    }

    public function Not() {
        return $this === self::True() ? self::False() : self::True();
    }
}

And test it out:, (*6)

Boolean::True()->Not() === Boolean::True(); //false
Boolean::True() === Boolean::False()->Not(); //true
Boolean::False()->Not()->Not() === Boolean::False(); //true

Cool, but pointless., (*7)

Lets do something useful and create the days of the week (as in summary) :, (*8)

final class DayOfWeek extends Enum\Simple {

    public static function Monday() { return self::Representing('Monday'); }

    public static function Tuesday() { return self::Representing('Tuesday'); }

    public static function Wednesday() { return self::Representing('Wednesday'); }

    public static function Thursday() { return self::Representing('Thursday'); }

    public static function Friday() { return self::Representing('Friday'); }

    public static function Saturday() { return self::Representing('Saturday'); }

    public static function Sunday() {  return self::Representing('Sunday'); }

    public function GetTomorrow() {
        if($this === self::Sunday()) {
            return self::Monday();
        }
        else {
            $All = self::All();
            return $All[array_search($this, $All) + 1];
        }
    }
}

Notice something? The enum values are simply represented by their method name., (*9)

Well, lets keep DRY and see how we go:, (*10)

final class DayOfWeek extends Enum\Simple {

    public static function Monday() { return self::Representing(__FUNCTION__); }

    public static function Tuesday() { return self::Representing(__FUNCTION__); }

    public static function Wednesday() { return self::Representing(__FUNCTION__); }

    public static function Thursday() { return self::Representing(__FUNCTION__); }

    public static function Friday() { return self::Representing(__FUNCTION__); }

    public static function Saturday() { return self::Representing(__FUNCTION__); }

    public static function Sunday() {  return self::Representing(__FUNCTION__); }

    public function GetTomorrow() {
        if($this === self::Sunday()) {
            return self::Monday();
        }
        else {
            $All = self::All();
            return $All[array_search($this, $All) + 1];
        }
    }
}

Well that didn't do much, and it is still extremely verbose! And ugly., (*11)

Relax, there is a solution:, (*12)

, (*13)

final class DayOfWeek extends \Enum\Simple {
    use \Enum\Values {
        _ as Monday;
        _ as Tuesday;
        _ as Wednesday;
        _ as Thursday;
        _ as Friday;
        _ as Saturday;
        _ as Sunday;
    }

    public function GetTomorrow() {
        if($this === self::Sunday()) {
            return self::Monday();
        }
        else {
            $All = self::All();
            return $All[array_search($this, $All) + 1];
        }
    }
}

That's better! Note that there will be no difference in functionality between the above three examples., (*14)

Note that using the \Enum\Values only works for PHP >5.4.16, (*15)

If your enums values are represented by the method names, you can utilise the \Enum\Values trait. This trait contains a single static method _. You can alias this method to the required enum values, and the aliased methods will return the enum representing the method name string., (*16)

Using this trait the equivalent Boolean would become:, (*17)

final class Boolean extends \Enum\Simple {
    use \Enum\Values {
        _ as True;
        _ as False;
    }

    public function Not() {
        return $this === self::True() ? self::False() : self::True();
    }
}

Conversion To String

Override the protected string ToString(mixed $Value) to customize the conversion to string:, (*18)

final class DayOfWeek extends \Enum\Simple {
    use \Enum\Values {
        _ as Monday;
        _ as Tuesday;
        _ as Wednesday;
        _ as Thursday;
        _ as Friday;
        _ as Saturday;
        _ as Sunday;
    }

    protected function ToString($Value) {
        return 'Today could be ' . strtolower($Value) . '.';
    }
}

echo DayOfWeek::Saturday(); //Today could be saturday.

Serialization

Enums values can also be fully serialized/unserialized using the Enum\Base::Serialize(Enum\Base $Enum) and Enum\Base::Unserialize(string $SerializedEnum) repectively. This will work for any defined enum., (*19)

If you want to un/serialize an enum of a specific type, you can can call either method in the context of the required enum type:, (*20)

$Monday = DayOfWeek::Monday();

$SerializedMonday = Enum\Base::Serialize($Monday);//Ok
$SerializedMonday = DayOfWeek::Serialize($Monday);//Ok
$SerializedMonday = MonthOfYear::Serialize($Monday);//ERROR!

$Monday = Enum\Base::Unserialize($SerializedMonday); //Ok
$Monday = DayOfWeek::Unserialize($SerializedMonday); //Ok
$Monday = MonthOfYear::Unserialize($SerializedMonday); //ERROR!

Comparison and Equality

An two enum instances of the same type, representing the same value must be equal. Comparison results using === operator can be seen below., (*21)

$Monday = DayOfWeek::Monday();
$Tuesday = DayOfWeek::Tuesday();

$Monday === DayOfWeek::Monday(); //true
$Monday === DayOfWeek::FromValue(DayOfWeek::Monday()->GetValue()); //true
$Monday === DayOfWeek::Unserialize(DayOfWeek::Serialize(DayOfWeek::Monday())); //true
$Monday === $Tuesday; //false

As you can see, within a enum there is only ever one instance representing any given value., (*22)

Clean comprehension API

  • Enum\Base::Map(callable $MappingCallback) Maps the enum instances with the supplied callback
  • Enum\Base::MapValues(callable $MappingCallback) Maps the represented values with the supplied callback
  • Enum\Base::Filter(callable $MappingCallback) Filters the enum instances with the supplied callback
  • Enum\Base::FilterByValue(callable $MappingCallback) Filters the enums by their represented value with the supplied callback
  • Enum\Base::FirstOrDefault(callable $MappingCallback) Returns the first enum according to the filter callback or the default value if none is matched
  • FirstOrDefaultByValue(callable $MappingCallback)

Usage

final class DayOfWeek extends \Enum\Simple {
    use \Enum\Values {
        _ as Monday;
        _ as Tuesday;
        _ as Wednesday;
        _ as Thursday;
        _ as Friday;
        _ as Saturday;
        _ as Sunday;
    }

    public static function IsWeekEnd(self $DayOfWeek) {
        return $DayOfWeek === self::Saturday() || $DayOfWeek === self::Sunday();
    }

    public static function GetWeekDays() {
        return self::Filter(function (self $DayOfWeek) {
            return !self::IsWeekEnd($DayOfWeek);
        });
    }

    public static function GetWeekEndDays() {
        return self::Filter([__CLASS__, 'IsWeekEnd']);
    }
}

A more sophisticated example

If your requirements are more complex, enums can represent any serializable value:, (*23)

class Country extends Enum\Simple {

    public static function USA() {
        return self::Representing(
                [
                    'Name' => 'United States of America',
                    'Population' => 317500000,
                    'Area' => 9826675
                ]);
    }

    public static function Australia() {
        return self::Representing(
                [
                    'Name' => 'Australia',
                    'Population' => 23351119,
                    'Area' => 7692024
                ]);
    }

    public static function SouthAfrica() {
        return self::Representing(
                [
                    'Name' => 'South Africa',
                    'Population' => 52981991,
                    'Area' => 1221037
                ]);
    }

    public static function FromName($Name) {
        return self::FirstOrDefaultByValue(
                function ($Value) use ($Name) {
                    return $Value['Name'] === $Name;
                });
    }

    protected function ToString($Value) {
        return $Value['Name'];
    }

    public function PopulationDensity() {
        $Country = $this->GetValue();

        return $Country['Population'] / $Country['Area'];
    }
}

We have defined an enum representing some countries and have provided methods to determine information on that data., (*24)

Usage

$SouthAfrica = Country::SouthAfrica();
echo sprintf('%s has a population density of: %s/Km²',
        $SouthAfrica,
        $SouthAfrica->PopulationDensity());

The Versions

20/04 2014

dev-master

9999999-dev http://www.github.com/TimeToogo/Enums

Enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.6

1.0.6.0 http://www.github.com/TimeToogo/HIPSTER-Enums

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.5

1.0.5.0 http://www.github.com/TimeToogo/HIPSTER-Enums

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.4

1.0.4.0 http://www.github.com/TimeToogo/HIPSTER-Enums

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.3

1.0.3.0 http://www.github.com/TimeToogo/HIPSTER-Enums

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.2

1.0.2.0 http://www.github.com/TimeToogo/HIPSTER-Enums

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.1

1.0.1.0 http://www.github.com/TimeToogo/HIPSTER-Enums

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration

19/01 2014

1.0.0

1.0.0.0 http://www.github.com/TimeToogo/PHP-Enum

Hipster enums for PHP 5.4+

  Sources   Download

MIT

The Requires

  • php >=5.4.0

 

by Elliot Levin

enum enumeration