Download the PHP package toobo/enum without Composer

On this page you can find all versions of the php package toobo/enum. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package enum

Enum

A single-class, Rust-inspired enum implementation for PHP.


license travis-ci status codecov.io release packagist PHP version requirement

Basic Enum

Concrete implementations must define public constants which will be the factory methods for the respective enum variations. Something like this:

After that, we can get an instance of the enum via "magic" factory methods like this:

and we can use the value in type declarations:

Because factory methods are implemented via __callStatic() it might be desirable to obtain IDE auto-complete via the @method annotation. E.g.:

Enum With Parameters

An awesome feature in Rust enum implementation is the possibility to add parameters to the enums.

This library provides a similar feature and creating enums with parameters is as simple as implementing an hydrate() method.

For example:

With such class, we can create instance of Move like this:

The argument passed to the "magic" factory methods is straight passed to hydrate, which means that as long as hydrate uses argument type declaration it is type-safe.

Sometimes it might be desirable that different enum variations accept different arguments, or that only some of the variations accept arguments.

This can be obtained via variation-specific hydrate methods that are named appending to hydrate the TitleCase version of the variation constant name.

E.g. for a variation whose constant is FOO_BAR the variation-specific hydrate method should be named hydrateFooBar.

The magic method will search for a variation-specific hydration method to call, if not found will search for the generic hydrate method. If none is found none will be called.

In case some arguments are passed, but no hydration method is found, an exception is raised by the package. In case a method is found it is always called, which means that if it is defined with any mandatory parameter and no argument is passed, an exception will be raised by PHP.

Enum With Sub-classes

The last and most advanced form of enum is the one built using sub-classes.

An example:

And the referenced Error class:

To be noted in the snippets above:

For example we could do something like this:

Enum Methods

Enum classes (no matter if "basic", with arguments, or with sub-classes) inherit some methods.

Getters

There are several getters:

Checking Enum Identity

Enum::isVariant() accepts a string and returns true if it matches the current enum variant. Basically, $enum->isVariant(Thing::FOO) is the same as $enum->variant() === Thing::FOO.

Enum::isAnyVariant() is the variadic version of Enum::isVariant() and arguments are combined with an OR logic, i.e. calling $this->isAnyVariant($a, $b, $c) is the same as calling: $this->isVariant($a) || $this->isVariant($b) || $this->isVariant($c).

Enum::is() accepts as argument an enum instance and returns a boolean that is true when the given enum and the enum the method is called on, are equivalent, which means they represent the same "variant" and, in case the enum accepts arguments, they also have same arguments.

There's also Enum::isAnyOf() which is the variadic version of Enum::is().

Custom Identity Check

Enum::is() works in the majority of cases as expected, but might be desirable to use a custom logic, especially for Enum with parameters which are objects.

In fact, for scalar or arrays arguments Enum::is() does a strict comparison (===) , but for objects it does a loose comparison (==).

This ensures that "similar" objects with different instances are considered equal. For example, if an enum class takes a Datetime object as parameter, and two instances of it took two different instances of Datetime representing the same point in time, the two enums will be considered matching by Enum::is().

However, might be desirable that such instances are considered matching if the day is the same in both of them, ignoring the time. This could be obtained by overriding Enum::is() with something like this:

We are using Enum::looksLike() to check that the two enums are "similar": they share the same Enum concrete class and either they also share same variation or any of them is a wildcard (more on this below).

Enum::looksLike() is a protected method that has a return type of bool|null: when it is capable to determine for sure if the two enums match without looking at construction arguments, it returns either true or false, when to determine identity is necessary to parse construction arguments it returns null.

In this latter case, the method shown above compares dates by day, as per requirement.

Wildcard Enum and Wildcard Parameter

Enum provides a "wildcard" static method _() that can be used to create an instance that is considered equivalent to any variant:

Calling the wildcard method directly on Enum, instead of on a sub-class, will create an instance that will match any enum, because Enum is super-class of all of them.

Moreover, Enum has a _ constant that can be used as "wildcard parameter" to be used to construct instances of enums that accept parameters:

In case the enum takes more parameters, it is possible to use wildcard parameter for only some of them.

of course it is possible to use wildcard parameters for all the arguments, which is basically equivalent to use Enum::isVariant():

It worth noting that some getters method behave differently for wildcard enums:

Finally, when Enum::describe() is called on a regular (non-wildcard) instance that makes use of some wildcard arguments, instead of the parameter type, the string "_" is used.

Pattern Matching (sort of)

In Rust, the most powerful and idiomatic way to deal with enums is pattern matching.

In PHP we don't have anything like that, but this library provides a Enum::match() method that enables something similar (unless we look at performance :D).

Let's take as example an enum:

we can do something like this:

Enum::match() accepts a variadic number of 2-items arrays, where the first item is either an enum instance or a string representing an enum variation and the second item is a callable.

Every first item is compared with is() (if it's an instance) or isVariant() (if it's a string) with the instance the method is called on, and in case of a match, the value returned by the related callback (2nd item) is immediately returned. The callback will receive as only argument the enum on which the method is called.

Enum::match() basically allows for logic-less switch implementations.

It is especially useful when the matching branch will make use of the enum instance, thanks to the fact that matching callback receives the enum as a parameter.

Another interesting feature is the possibility to use wildcard parameter to implicitly apply matching logic, without any if.

For example, in the snippet above, the "administrator" user is matched by requiring a specific user name ("root"), ignoring the user id.

For a comparison, an equivalent code would be:

Which is slightly less code (13 lines VS 14) but it has an higher cyclomatic complexity which will increase linearly with more variants (enum in this example just have two) whereas usage of match keep the cyclomatic complexity fixed at 1 no matter the number of variants.

Moreover, we used closures in the match example above, but using defined functions/methods/invokable it would be less code than a switch and more flexible too. E.g.:

Each invokable objects __invoke() method will receive the Response object as parameter and they can do whatever they want with it, without any need to know from where the object comes from.

But there's more.

Matcher Callback

Enum provides an utility method to encapsulate the matching logic in a callable object that could be stored and/or passed around. The (static) method Enum::matcher() accepts as argument the same variadic list of arrays that can be passed to Enum::match() and returns a callable object which accepts an enum instance and returns the result of applying the matching logic to it.

The matcher object could be injected into objects or passed as parameter...

Matching Pattern Priority

You might have noticed how in snippet above the pattern Response::ERROR(Response::_, 404) can match if the string pattern Response::ERROR is placed before it in the list, and in theory would "cover" it, matching any error response.

This works because there's a priority being applied when matching patterns. In order:

  1. First of all, enum instances without any wildcard parameter are parsed. In case of multiple such instances, order matters;
  2. enum instances using wildcard parameters are matched. These are ordered by the number of used wildcard parameters: the less wildcard parameters they use, the more priority they take. In case of multiple such instances with same number of wildcard parameters, order matters;
  3. enum variation constants are parsed. In case of multiple such instances, order matters;
  4. wildcard enums (those crated via _() method) are parsed. In case of multiple such instances, order matters;
  5. Finally, the callback associated with a catch all pattern, if found, is executed. There are two ways of define a catch all pattern: the match all wildcard instance Enum::_(), or just the wildcard constant: Enum::_ . In the case multiple of such catch all patterns are present, only the first is executed (if nothing else matches first) and others are ignored.

Note on Constructors

For Enum classes, __construct() can't be called (because private) nor can be overridden, because final: so the only clean way to obtain enum instances is to call the magic methods.

The reason is that the logic in the rest of the class relies on the __callStatic method being called.

It worth also noting that hydrate methods are not constructors and even if that provides some benefits, (for example all the enum getters are available during hydration) it also brings the issue that extra care should be put on not leaving properties undefined.

For example, in the class:

Because there's no constructor, to be sure $steps is set, a value is assigned in the declaration (private $steps = 0).

In this way, steps() method can be safely declared with an int type declaration.

An alternative is to don't assign a value in the property declaration and declare the return type of steps() as ?int, dealing in the rest of the class with the fact that $steps has a type of int|null and not int.


All versions of enum with dependencies

PHP Build Version
Package Version
Requires php Version >=7.2
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package toobo/enum contains the following files

Loading the files please wait ....