PHP Classes

How Would You Create Enums in PHP - Div PHP Enum Class package blog

Recommend this page to a friend!
  All package blogs All package blogs   Div PHP Enum Class Div PHP Enum Class   Blog Div PHP Enum Class package blog   RSS 1.0 feed RSS 2.0 feed   Blog How Would You Create ...  
  Post a comment Post a comment   See comments See comments (0)   Trackbacks (0)  

Author:

Viewers: 1,075

Last month viewers: 372

Package: Div PHP Enum Class

Enums, or enumerations, are types of values that can be assigned to a variable with a limited number of possible values.

Until today PHP does not have a native enum type. It offers a very basic implementation using SPL extension, but I prefer to believe that implementation is not ideal.

Alternatively, the Div PHP Enum package provides is a solution for this using classes. Thanks to some interesting features of PHP, you can make a taxonomy (hierarchy of terms) and give behavior to each term similar to what we can achieve using the Java language.

Read read article to learn how you can implement PHP enums using pure PHP code, thus without additional extensions.





Loaded Article

Introduction to Enums in PHP

An enumeration type, "enum" for short, is a data type that is used to define unique values that are associated to names. Enums can be used instead of hard coded strings to represent, for example, the status of a blog post in a structured and typed way.

Until today PHP does not have a native enum type. It offers a very basic  implementation using SPL extension, but I prefer to believe that implementation is not ideal.

There is a popular package written by Matthieu Napoli called myclabs/php-enum. It is a package that many of us have been using in countless projects. It is really awesome.

However, I prefer to believe that when we use the myclabs/php-enum package we lose the benefits of static analysis like being able to auto-complete values in PHP IDE tools as well refactoring the code when we make changes that affect many parts of a project.

Alternatively, the Div PHP Enum package provides is a solution for this using classes. Thanks to some interesting features of PHP, you can make a taxonomy (hierarchy of terms) and give behavior to each term similar to what we can achieve using the Java language.

In July 2019, I wrote a gist while I was searching a solution for this. Later I have converted the gist into a real project.

The problem

Some solutions use PHP constants, but I prefer to believe they are not ideal because they have limitations. For instance how can you validate that HOT or COLD are acceptable as function parameter values?

<?php
const HOT = 1;

function doSomething(int $temperature) { /* ... */}
const COLD = 2;
const FIRE = 1;
const ICE = 2;
doSomething(FIRE);

The Solution

Use PHP!

The class divengine\enum can help solving the problem using just pure PHP. but keep in mind: the most important solution is the concept of this library.

It uses class names as a way to define enumerated values.

We need have built-in support for enums in PHP, but, for now, this is a solution that works.

With this class, you can solve the following problems:

1. Constants with different names and equal value can be used in the declaration of function arguments allowing PHP to do type checking using type hinting support.

2. It also makes it possible for PHP IDEs and other types of tools to perform loose static analysis benefits like auto completion and refactoring

3. It can also be used in PHPDOC like documentation comments to provide type hints to also help solving the problem 1.

Examples

First, define your enums. You can build a taxonomy by defining enums with values that represent categories of classes of objects.
<?php

namespace MyEnums;

use divengine\enum;

class Temperature extends enum {/Father of all types of temperatures/}
class ExtremeTemperature extends Temperature {/Father of all types of extreme temperatures/}
class FIRE extends ExtremeTemperature {}
class ICE extends ExtremeTemperature {}

class NormalTemperature extends Temperature {/Father of all types of normal temperatures/}
class HOT extends NormalTemperature {}
class COOL extends NormalTemperature {}
class COLD extends NormalTemperature {}

Second use your enums:

<?php

use MyEnums;

// Constants are good tricks, but optional
const COOL = COOL::class;

class AllTemperatures {
    const COOL = COOL::class; // maybe better
    const HOT = 'Enums\\HOT';  // ugly !!!

    //...
}

// Define some function with type hinting
function WhatShouldIdo(Temperature $temperature)
{
    switch (true) {
        case $temperature instanceof ExtremeTemperature:
            switch (true) {
                case $temperature instanceof FIRE:
                    return "Call the fire department";

                case $temperature instanceof ICE:
                    return "Warm up";
            }
            break;

        case $temperature instanceof NormalTemperature:
            switch ($temperature) {

                case HOT::class: // compare using classname
                    return "Drink a bear :D";

                case COOL or AllTemperatures::COOL: // compare using constants
                    return "Just go away !";

                case 'Enums\\COLD': // compare using string, ugly !!!
                    return "Wear a coat";
            }

            break;
    }

    return "I don't know";
}

// Call to function with a instance of any Temperature
echo WhatShouldIdo(new HOT()) . PHP_EOL;

Do you like Java programming language? Here is similar code using Java

You actually can use switch statements on enums, but you can not switch do the same using Strings before Java 7.

You may consider using polymorphic method dispatch with Java enums rather than an explicit switch. Note that enums are objects in Java, not just symbols for ints like they are in C/C++.

You can have a method using an enum type. Then instead of writing a switch, just call the method - one line of code: done!

One of the nice things about this approach is that it is simply impossible to get certain types of errors. You can't miss a switch case (you can incorrectly implement a method for a particular constant, but there's nothing that will ever totally prevent that from happening!). There's no switch "default" to worry about. Also, I've seen code that puts enum constants into arrays and then indexes into the arrays - this opens the possibility of array index out of bounds exceptions - just use the enum! Java enums are very, very powerful. Learn all that you can about them to use them effectively.

public enum Temperature {
 HOT {
 @Override
 public void whatShouldIdo() {
   System.out.println("Drink a bear!");
  }
 },
 COLD {
  @Override
  public void whatShouldIdo() {
   System.out.println("Wear a coat!");
  }
 };

 public abstract void whatShouldIdo();
// ...
void aMethodSomewhere(final Temperature temperature) {

// here is where the switch would be,
// now it's one line of code!
} doSomeStuff();
temperature.whatShouldIdo(); doSomeOtherStuff(); }

Also note if you have several enum constants that all have the same behavior for a particular method, you can simply gather that shared code in an enum method that is not overridden by every constant (final protected) and then call that method from the appropriate methods.

So, add "final protected void commonMethod() { ... }" and then the implementation of method() in each constant would just call commonMethod().

And.... what about PHP ?

Here follows a similar solution:

<?php
abstract class Temperature extends divengine\enum {
 public function whatShouldIdo() {}
}
class HOT extends Temperature {
 public function whatShouldIdo() {
  echo "Drink a bear!";
 }
}
class COLD extends Temperature {
 public function whatShouldIdo() {
  echo "Wear a coat!";
 }
}
// ....

function someStuff(Temperature $t) { $t->whatShouldIdo(); } someStuff( new HOT() );

Conclusion

This is my contribution to implement a flexible solution to implement enums in PHP. The project will continue to have improvements in terms of features and documentation. I hope this solution serves many of you that like me had the need for a better approach to implement enumerated values in PHP.

If you liked this article share it with other PHP developer colleagues that like you appreciated learning more about PHP techniques to implement better PHP projects.

If you have questions or doubts, feel free to comment about this project below.




You need to be a registered user or login to post a comment

1,611,040 PHP developers registered to the PHP Classes site.
Be One of Us!

Login Immediately with your account on:



Comments:

No comments were submitted yet.



  Post a comment Post a comment   See comments See comments (0)   Trackbacks (0)  
  All package blogs All package blogs   Div PHP Enum Class Div PHP Enum Class   Blog Div PHP Enum Class package blog   RSS 1.0 feed RSS 2.0 feed   Blog How Would You Create ...