PHPackages                             ph-il/enums - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. ph-il/enums

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

ph-il/enums
===========

Zero-dependencies package to supercharge enum functionalities via helper traits.

0.2.1(2mo ago)031MITPHPPHP ^8.3

Since Feb 19Pushed 2mo agoCompare

[ Source](https://github.com/parler-haut-interagir-librement/enums)[ Packagist](https://packagist.org/packages/ph-il/enums)[ Docs](https://ph-il.ca)[ RSS](/packages/ph-il-enums/feed)WikiDiscussions main Synced today

READMEChangelog (3)Dependencies (26)Versions (4)Used By (0)

Enums
=====

[](#enums)

[![Author](https://camo.githubusercontent.com/44362f1e38c1e2ea97f076c3780f88f2c4d1b1fe4c54fc01045cf32c0c280b3e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f617574686f722d70682d2d696c2d626c75653f6c6f676f3d676974687562267374796c653d7374796c653d666f722d7468652d6261646765266c6f676f53697a653d6175746f)](https://github.com/ph-il)[![PHP Version](https://camo.githubusercontent.com/9726fca1da818e93120dd78ca5f53b5e245acb36c21529e4c3b3663de62bb5c7/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f7068702d762f70682d696c2f656e756d733f636f6c6f723d253233373737424234266c6f676f3d706870267374796c653d666f722d7468652d6261646765266c6f676f53697a653d6175746f)](https://www.php.net)[![Latest Version](https://camo.githubusercontent.com/0da4fc6587f75cc873454e00f10f9b54ca6fcb638f925be8161307634a245401/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f70682d696c2f656e756d732e7376673f6c6162656c3d76657273696f6e267374796c653d666f722d7468652d6261646765266c6f676f3d766974657373266c6f676f436f6c6f723d666666266c6f676f53697a653d6175746f)](https://packagist.org/packages/ph-il/enums)[![Software License](https://camo.githubusercontent.com/9ea7157111981e64ce15546f9a0acc7710430886a175c7c143eec8b6b26da197/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d626c75652e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d6c65726e61266c6f676f436f6c6f723d666666266c6f676f53697a653d6175746f)](LICENSE)[![Build Status](https://camo.githubusercontent.com/1381f75b770a7dab6a6df83bbdcae5182164f801a28fc2fbd93cedad8c1dfecc/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f7061726c65722d686175742d696e746572616769722d6c696272656d656e742f656e756d732f6275696c642e796d6c3f6272616e63683d6d6173746572267374796c653d666f722d7468652d6261646765266c6f676f3d676974687562266c6f676f53697a653d6175746f)](https://github.com/parler-haut-interagir-librement/enums/actions?query=workflow%3Abuild)[![Code Quality](https://camo.githubusercontent.com/758a0f2489334ef608e65914832a242275eb5902644346dfae4e2b43cfcc7f91/68747470733a2f2f696d672e736869656c64732e696f2f636f646163792f67726164652f34326437326166303963353534303731626538633763626436356335376537393f7374796c653d666f722d7468652d6261646765266c6f676f3d636f64616379266c6f676f53697a653d6175746f)](https://app.codacy.com/gh/parler-haut-interagir-librement/enums/dashboard)[![Coverage](https://camo.githubusercontent.com/6385df045c4f632f8ae4756f06ab2110c341b05c58a5f7b917a6529a3b697dc0/68747470733a2f2f696d672e736869656c64732e696f2f636f646163792f636f7665726167652f34326437326166303963353534303731626538633763626436356335376537393f7374796c653d666f722d7468652d6261646765266c6f676f3d636f64616379266c6f676f53697a653d6175746f)](https://app.codacy.com/gh/parler-haut-interagir-librement/enums/dashboard)[![PHPStan Level](https://camo.githubusercontent.com/047424e0daa5f9eb89165511c840728f3626285cc1c865418f2367831b7f510c/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f7068707374616e2d6d61782d737563636573733f7374796c653d666f722d7468652d6261646765266c6f676f3d646174613a696d6167652f706e673b6261736536342c6956424f5277304b47676f414141414e53556845556741414143414141414167434159414141427a656e72304141414762306c455156523432753158653142555a52532f79344b67386f6952334643434255795345535a4252436961426e6d45734f7a65537a73672b4b7859594f3964454566744e52715a6a78343046525a6b5470716d4f7a3553324c73586c455a42636961746b516e484447596147644679314570474d486c2f702f5064466c7432726b354f2b4a396e356e412f767466356e6564336c6e6c49537052686166426c4c524c4843744a475672422f5a4244736177326c55717a526547414334364473745459666e534347556a61614476677841436f366a337655656e4e64496d65525871646e575635617a3572726e7a655a7a6e6a384a2b4535467473636c68663373344a3443532f6f52783542766f6e385a553635464759517841776366383561374365527a2b4334315448656a75657964435a3741414b33346e7776336b48502f6f554b644f4c344b373235386646374375643432374f3438525165476b49474a37374e38665a716c726366525034642f78393057516648584c65427439645472536c776c33563635796e574c4d315345413271624e51636b626534586d77773130486d79337368696430434d636d6c454a745344736c35565a42646641674d7649337575522b6d6f4a714e364c61786d70734f42654c43446d546966434239325263516d6241554a767471414c63357351723870383667594243634664427139774f696e374e5161783665776c423672714c5a486632334650313079336c6a36754a74454267324878695643747a64335345774d4243696f364e6839757a5a344f2f764c774f5a344f554e4d324e79494750467276757a42472f2f6c5250732b5651326b316b692b65506b64383462736b7a375946705967697a457a3838503876507a596666753364445330674a4e545531515856304e71616d70524b31574977676669453471684f7969673072432b7043764b3851556f4d4c37754a564841356b635155703344537071576a6333642f4479386f4b696f694c6f367571436f614568754862314b765430394141684246706257346c4f70794d797949425153436d6f55514c517a676e694e767a2b6f624232485332527742674536644f7843794a6f676d4e6b503275315772687734514a30332b69477252395845643343544e426e366543626f3430775044774d645856314246314456473571694574626f78535550364a37312b44334e775541684c4f4952517a6d376c6e6e68595576375146762f79445a2f4c6d3575624b3244564939695a386252384a4474454235376c4e7a454e514e364f6a6f49476c70616249565a7359614d544f2b6872696b525241314a786d5358396845372f734a745679463338744b735543565a7842687a396a49337747542f514a6c41447a50417958726e6a306b496e7a47485143524d794f672f65643275486a784975453454675951487132444c4a71756d617368592b6c6e734d433447564335646f365856754b396c2b34536b4e38792b47665965564a6e32672b2b553751796750543064426759474944765435386d6e46355051636a433833507a5346396648375331745a47456841515a514f54384a61413331376f496b4d366a533875564c53447a4f517167323355682b4d6c6b4f66303047673063503334632b7676373455527a4d396e34316762792f7276766b63374f54686c415455334e4347594a5558743451614c75545977426354534f426d6a315244374434547369783442794f6a5a52462f7a677570444562675a336a346c792f71656b704e44306f35615134344853344f416773567174493167545a4f303149624730615031626b6e6e7843445576417248692b42306c4a536c7a676c5446594f3275644633516c39544372486e356f45497265487036516c5255464a53556c4a43717169705357566c4a38764c79434759494653374853337a476138376d76346c636a4c774c6c53746c4c544b59595555416c76726c444763573435774b785858366171485a4e75744d2b316f51424846546577414b6b6f48342b7671436a3438505941475335796235616d6a4e6f4f2b435532534c35334e4b70444430767848486d4f4a6972374c357855765a676d307573325231343253634f4979567159766c70575534586f4849503844584c32622b776a6457655868365532466a6d49494b6d625741595046524d75733632682f676549766a4f51596c707544797351724c4c364765723439486757386a7176585568493755764462396961535444714874794974694635537577356577462f4e6438564a367a6c68736e30366245687758344e79664376754745655270546d68346d6b47363879447079757a42394555636a553561776241676e63506c4165536441514552307a436e647a715662655843347144734d70764745594258526e734478344e33417566314643546a5449615674592f51546d643049386242566d316b656a45756255664f30317671496d6e336334395837717065714939696e4967746270784b3359724b66494a43742b4f6556326e665556465234636134456b56454e794137676b59634d66423152354d4d6d785a37657a2f324b463553534e3179562b3135385550734a54305a4263493262524c744958476f5975354665724f55694a65314f66734c335845574834336c324b532b694a46392b53344670634e6773632b6a3863543848346f31626650672f716b4c743530754a31527a644d7347673055717766454e313134507762314374575447672b59395535436c4b397837785557493742493556515670304156635133625a6b51686d6e45676448684b794e535a65313663727442496c63377349623663524c6674325043676f4b476a696a4244746a72415137613345644d73787a4952666c414649685062366d48596d5977582b57426c505167736b6867567279794a4351794e79424c73425164513666677351687974364d534f4f73575a37676248387745546d67524b41696a61744e4c384e676d30787834744c6373707330577a7834616c306a586c493430422f413370613134344d447453674141414141456c46546b5375516d4343266c6f676f53697a653d6175746f)](https://phpstan.org/)[![Total Downloads](https://camo.githubusercontent.com/cb2a57e34821bd1348f2befd0ed918168a12b1b12ae0ae0f0d4b50d2233de7af/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f70682d696c2f656e756d732e7376673f7374796c653d666f722d7468652d6261646765266c6f676f3d7061636b6167697374266c6f676f53697a653d6175746f)](https://packagist.org/packages/ph-il/enums)

A zero-dependencies collection of enum helper traits for PHP.

Tip

Need to supercharge enums in a Symfony application?

Consider using [Enums Bundle](https://github.com/parler-haut-interagir-librement/enums-bundle) instead.

Available Traits
----------------

[](#available-traits)

- [`AsInvocableEnum`](#asinvocableenum) — Access enum values via static calls or invocation
- [`AsNameableEnum`](#asnameableenum) — Get a list of case names
- [`AsValuableEnum`](#asvaluableenum) — Get a list of case values
- [`AsSelectableEnum`](#asselectableenum) — Get an associative array of names → values
- [`AsComparableEnum`](#AsComparableEnum) — Compare enum cases fluently
- [`AsFromambleEnum`](#AsFromambleEnum) — Add `from()`/`tryFrom()` to pure enums and `fromName()`/`tryFromName()` to all enums
- [`AsMetadableEnum`](#AsMetadableEnum) — Attach metadata to enum cases via attributes
- [`AsSelfAwareableEnum`](#asselfawareableenum) — Introspect whether an enum is pure, backed, backed by int or string
- [`AsStringSelectableEnum`](#asstringselectableenum) — Generate string representations of enum options

Table of Contents
-----------------

[](#table-of-contents)

- [Installation](#installation)
- [Usage](#usage)
    - [`AsInvocableEnum`](#asinvocableenum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum)
        - [Use static calls to get the primitive value](#use-static-calls-to-get-the-primitive-value)
        - [Invoke instances to get the primitive value](#invoke-instances-to-get-the-primitive-value)
    - [`AsNameableEnum`](#asnameableenum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-1)
        - [`names()`](#use-the-names-method)
    - [`AsValuableEnum`](#asvaluableenum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-2)
        - [`values()`](#use-the-values-method)
    - [`AsSelectableEnum`](#asselectableenum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-3)
        - [`options()`](#use-the-options-method)
    - [`AsComparableEnum`](#AsComparableEnum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-4)
        - [`is()` — Check if the case matches a target](#is--check-if-the-case-matches-a-target)
        - [``isNot()` — Check if the case does not match a target`](#isnot--check-if-the-case-does-not-match-a-target)
        - [`in()` — Check if the case is in a list of targets](#in--check-if-the-case-is-in-a-list-of-targets)
        - [`notIn()` — Check if the case is not in a list of targets](#notin--check-if-the-case-is-not-in-a-list-of-targets)
        - [`has()` — Check if the enum includes a given target (static)](#has--check-if-the-enum-includes-a-given-target-static)
        - [`doesntHave()` — Check if the enum does not include a given target (static)](#doesnthave--check-if-the-enum-does-not-include-a-given-target-static)
        - [`equalsOneOf()` — Check if the case matches any case in an array](#equalsoneof--check-if-the-case-matches-any-case-in-an-array)
        - [`notEqualsOneOf()` — Check if the case does not match any case in an array](#notequalsoneof--check-if-the-case-does-not-match-any-case-in-an-array)
    - [`AsFromambleEnum`](#AsFromambleEnum)
        - [Important Notes](#important-notes)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-5)
        - [`from()` — Get a pure enum case by name or throw](#from--get-a-pure-enum-case-by-name-or-throw)
        - [`tryFrom()` — Get a pure enum case by name or null](#tryfrom--get-a-pure-enum-case-by-name-or-null)
        - [`fromName()` — Get any enum case by name or throw](#fromname--get-any-enum-case-by-name-or-throw)
        - [`tryFromName()` — Get any enum case by name or null](#tryfromname--get-any-enum-case-by-name-or-null)
    - [`AsMetadableEnum`](#AsMetadableEnum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-6)
        - [Access the Metadata](#access-the-metadata)
        - [Creating Meta Properties](#creating-meta-properties)
            - [Custom method name — Override `customMethodName()` to change the accessor](#custom-method-name--override-custommethodname-to-change-the-accessor)
            - [Value transformation — Override `transform()` to modify the stored value](#value-transformation--override-transform-to-modify-the-stored-value)
            - [Default value — Override `defaultValue()` to set a default value](#default-value--override-defaultvalue-so-cases-without-the-attribute-still-return-a-value)
        - [`fromMeta()` — Get the first case matching a meta value or throw](#frommeta--get-the-first-case-matching-a-meta-value-or-throw)
        - [`tryFromMeta()` — Get the first case matching a meta value or null](#tryfrommeta--get-the-first-case-matching-a-meta-value-or-null)
        - [Included Meta Properties](#included-meta-properties)
            - [Description](#description)
            - [Group](#group)
            - [Label](#label)
        - [Recommandations](#recommendation-use-annotations-and-traits)
    - [`AsSelfAwareableEnum`](#asselfawareableenum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-7)
        - [`isPure()` — Check if the enum is a pure enum (no backing type)](#ispure--check-if-the-enum-is-a-pure-enum-no-backing-type)
        - [`isBacked()` — Check if the enum is backed](#isbacked--check-if-the-enum-is-backed)
        - [`isBackedByInteger()` — Check if the enum is backed by `int`](#isbackedbyinteger--check-if-the-enum-is-backed-by-int)
        - [`isBackedByString()` — Check if the enum is backed by `string`](#isbackedbystring--check-if-the-enum-is-backed-by-string)
    - [`AsStringSelectableEnum`](#asstringselectableenum)
        - [Apply the trait on your enum](#apply-the-trait-on-your-enum-8)
        - [`stringOptions()` — Generate a formatted string from enum cases](#stringoptions--generate-a-formatted-string-from-enum-cases)
- [PHPStan](#phpstan)
- [Development](#development)
- [Todo](#todo)

Installation
------------

[](#installation)

PHP 8.3+ is required.

Via Composer :

```
composer require ph-il/enums
```

Usage
-----

[](#usage)

To supercharge our enums with all the features (except [AsStringSelectableEnum](#asstringselectableenum)) provided by this package, we can let our enums use the Enumerates trait:

```
use Phil\Enums\Traits\AsEnumerableEnumTrait;

enum PureEnum
{
    use AsEnumerableEnumTrait;

    case ONE;
    case TWO;
    case THREE;
}

enum BackedEnum: int
{
    use AsEnumerableEnumTrait;

    case ONE = 1;
    case TWO = 2;
    case THREE = 3;
}
```

### AsInvocableEnum

[](#asinvocableenum)

Get the value of a backed enum, or the name of a pure enum, by "invoking" it — either statically (`BackedEnum::THREE()` instead of `BackedEnum::THREE->value`), or as an instance (`$enum()`).

Use enums as array keys without appending `->value`:

```
'statuses' => [
    TaskStatus::INCOMPLETE() => ['some configuration'],
    TaskStatus::COMPLETED() => ['some configuration'],
],
```

Or pass primitive values directly:

```
public function updateStatus(int $status): void;

$task->updateStatus(TaskStatus::COMPLETED());
```

The main point: this is all without having to append `->value` to everything.

This approach also has *decent* IDE support. You get autosuggestions while typing, and then you just append `()`:

```
BackedEnum::THREE; // => BackedEnum instance
BackedEnum::THREE(); // => 3
```

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum)

```
use Phil\Enums\Traits\AsInvocableEnumTrait;

enum TaskStatus: int
{
    use AsInvocableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}
enum Role
{
    use AsInvocableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}

enum PureEnum
{
    use AsInvocableEnumTrait;

    case ONE;
    case TWO;
    case THREE;
}

enum BackedEnum: int
{
    use AsInvocableEnumTrait;

    case ONE = 1;
    case TWO = 2;
    case THREE = 3;
}
```

#### Use static calls to get the primitive value

[](#use-static-calls-to-get-the-primitive-value)

```
BackedEnum::ONE(); // 1
BackedEnum::TWO(); // 2
BackedEnum::THREE(); // 3
PureEnum::ONE(); // 'ONE'
PureEnum::TWO(); // 'TWO'
PureEnum::THREE(); // 'THREE'
```

#### Invoke instances to get the primitive value

[](#invoke-instances-to-get-the-primitive-value)

```
public function updateStatus(TaskStatus $status, Role $role)
{
    $this->record->setStatus($status(), $role());
}
```

### AsNameableEnum

[](#asnameableenum)

Returns a list of case **names** in the enum.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-1)

```
use Phil\Enums\Traits\AsNameableEnumTrait;

enum TaskStatus: int
{
    use AsNameableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsNameableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### Use the `names()` method

[](#use-the-names-method)

```
TaskStatus::names(); // ['INCOMPLETE', 'COMPLETED', 'CANCELED']
Role::names(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
```

### AsValuableEnum

[](#asvaluableenum)

Returns a list of case **values** for backed enums, or a list of case **names** for pure enums.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-2)

```
use Phil\Enums\Traits\AsValuableEnumTrait;

enum TaskStatus: int
{
    use AsValuableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsValuableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### Use the `values()` method

[](#use-the-values-method)

```
TaskStatus::values(); // [0, 1, 2]
Role::values(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
```

### AsSelectableEnum

[](#asselectableenum)

Returns an associative array of `[case name => case value]` for backed enums, or an indexed array of names for pure enums.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-3)

```
use Phil\Enums\Traits\AsSelectableEnumTrait;

enum TaskStatus: int
{
    use AsSelectableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsSelectableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### Use the `options()` method

[](#use-the-options-method)

```
TaskStatus::options(); // ['INCOMPLETE' => 0, 'COMPLETED' => 1, 'CANCELED' => 2]
Role::options(); // ['ADMINISTRATOR', 'SUBSCRIBER', 'GUEST']
```

### AsComparableEnum

[](#ascomparableenum)

Compare enum cases using fluent instance methods and static helpers.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-4)

```
use Phil\Enums\Traits\AsComparableEnumTrait;

enum TaskStatus: int
{
    use AsComparableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsComparableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### `is()` — Check if the case matches a target

[](#is--check-if-the-case-matches-a-target)

```
TaskStatus::INCOMPLETE->is(TaskStatus::INCOMPLETE); // true
TaskStatus::INCOMPLETE->is(TaskStatus::COMPLETED); // false
Role::ADMINISTRATOR->is(Role::ADMINISTRATOR); // true
Role::ADMINISTRATOR->is(Role::NOBODY); // false
```

#### `isNot()` — Check if the case does not match a target

[](#isnot--check-if-the-case-does-not-match-a-target)

```
TaskStatus::INCOMPLETE->isNot(TaskStatus::INCOMPLETE); // false
TaskStatus::INCOMPLETE->isNot(TaskStatus::COMPLETED); // true
Role::ADMINISTRATOR->isNot(Role::ADMINISTRATOR); // false
Role::ADMINISTRATOR->isNot(Role::NOBODY); // true
```

#### `in()` — Check if the case is in a list of targets

[](#in--check-if-the-case-is-in-a-list-of-targets)

```
TaskStatus::INCOMPLETE->in([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // true
TaskStatus::INCOMPLETE->in([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // false
Role::ADMINISTRATOR->in([Role::ADMINISTRATOR, Role::GUEST]); // true
Role::ADMINISTRATOR->in([Role::SUBSCRIBER, Role::GUEST]); // false
```

#### `notIn()` — Check if the case is not in a list of targets

[](#notin--check-if-the-case-is-not-in-a-list-of-targets)

```
TaskStatus::INCOMPLETE->notIn([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // false
TaskStatus::INCOMPLETE->notIn([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // true
Role::ADMINISTRATOR->notIn([Role::ADMINISTRATOR, Role::GUEST]); // false
Role::ADMINISTRATOR->notIn([Role::SUBSCRIBER, Role::GUEST]); // true
```

#### `has()` — Check if the enum includes a given target (static)

[](#has--check-if-the-enum-includes-a-given-target-static)

```
TaskStatus::has(TaskStatus::INCOMPLETE); // true
```

#### `doesntHave()` — Check if the enum does not include a given target (static)

[](#doesnthave--check-if-the-enum-does-not-include-a-given-target-static)

```
TaskStatus::doesntHave(TaskStatus::INCOMPLETE); // false
```

#### `equalsOneOf()` — Check if the case matches any case in an array

[](#equalsoneof--check-if-the-case-matches-any-case-in-an-array)

```
TaskStatus::INCOMPLETE->equalsOneOf([TaskStatus::INCOMPLETE, TaskStatus::COMPLETED]); // true
```

#### `notEqualsOneOf()` — Check if the case does not match any case in an array

[](#notequalsoneof--check-if-the-case-does-not-match-any-case-in-an-array)

```
TaskStatus::INCOMPLETE->notEqualsOneOf([TaskStatus::COMPLETED, TaskStatus::CANCELED]); // true
```

### AsFromambleEnum

[](#asfromambleenum)

Adds `from()` and `tryFrom()` to **pure** enums, and adds `fromName()` and `tryFromName()` to **all** enums.

#### Important Notes:

[](#important-notes)

-
- `BackedEnum` instances already implement their own `from()` and `tryFrom()` methods, which will not be overridden by this trait.
- For pure enums, `from()` and `tryFrom()` are functionally equivalent to `fromName()` and `tryFromName()`.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-5)

```
use Phil\Enums\AsFromambleEnumTrait;

enum TaskStatus: int
{
    use AsFromambleEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsFromambleEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### `from()` — Get a pure enum case by name or throw

[](#from--get-a-pure-enum-case-by-name-or-throw)

```
Role::from('ADMINISTRATOR'); // Role::ADMINISTRATOR
Role::from('NOBODY'); // Error: ValueError
```

#### `tryFrom()` — Get a pure enum case by name or null

[](#tryfrom--get-a-pure-enum-case-by-name-or-null)

```
Role::tryFrom('GUEST'); // Role::GUEST
Role::tryFrom('NEVER'); // null
```

#### `fromName()` — Get any enum case by name or throw

[](#fromname--get-any-enum-case-by-name-or-throw)

```
TaskStatus::fromName('INCOMPLETE'); // TaskStatus::INCOMPLETE
TaskStatus::fromName('MISSING'); // Error: ValueError
Role::fromName('SUBSCRIBER'); // Role::SUBSCRIBER
Role::fromName('HACKER'); // Error: ValueError
```

#### `tryFromName()` — Get any enum case by name or null

[](#tryfromname--get-any-enum-case-by-name-or-null)

```
TaskStatus::tryFromName('COMPLETED'); // TaskStatus::COMPLETED
TaskStatus::tryFromName('NOTHING'); // null
Role::tryFromName('GUEST'); // Role::GUEST
Role::tryFromName('TESTER'); // null
```

### AsMetadableEnum

[](#asmetadableenum)

Attach metadata to enum cases using PHP attributes.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-6)

```
use App\Enums\MetaProperties\Color;
use Phil\Enums\AsMetadableEnumTrait;
use Phil\Enums\Attribute\Description;
use Phil\Enums\Attribute\Meta;

#[Meta(Description::class, Color::class)]
enum TaskStatus: int
{
    use AsMetadableEnumTrait;

    #[Description('Incomplete Task')] #[Color('red')]
    case INCOMPLETE = 0;

    #[Description('Completed Task')] #[Color('green')]
    case COMPLETED = 1;

    #[Description('Canceled Task')] #[Color('gray')]
    case CANCELED = 2;
}
```

Explanation:

- `Description` is an exemple that we do provide as a class attributes for meta properties
- `Color` is userland class attributes — meta properties
- The `#[Meta]` attribute on the enum declares which meta properties are enabled
- Each case must have the declared meta properties applied (unless the meta property defines a `defaultValue()`)

#### Access the metadata

[](#access-the-metadata)

```
TaskStatus::INCOMPLETE->description(); // 'Incomplete Task'
TaskStatus::COMPLETED->color(); // 'green'
```

#### Creating meta properties

[](#creating-meta-properties)

Each meta property is a class extending `AbstractMetaProperty`:

```
#[Attribute]
class Color extends AbstractMetaProperty {}

#[Attribute]
class Description extends AbstractMetaProperty {}
```

Inside the class, you can customize a few things.

##### Custom method name — Override `customMethodName()` to change the accessor

[](#custom-method-name--override-custommethodname-to-change-the-accessor)

For instance, you may want to use a different method name than the one derived from the class name (`Description` becomes `description()` by default).

To do that, override the `method()` method on the meta property:

```
#[Attribute]
class Description extends AbstractMetaProperty
{
    public static function customMethodName(): ?string
    {
        return 'note';
    }
}
```

With the code above, the description of a case will be accessible as `TaskStatus::INCOMPLETE->note()`.

#### Value transformation — Override `transform()` to modify the stored value

[](#value-transformation--override-transform-to-modify-the-stored-value)

Another thing you can customize is the passed value. For instance, to wrap a color name like `text-{$color}-500`, you'd add the following `transform()` method:

```
#[Attribute]
class Color extends MetaProperty
{
    protected function transform(mixed $value): mixed
    {
        return "text-{$value}-500";
    }
}
```

And now the returned color will be correctly transformed:

```
TaskStatus::COMPLETED->color(); // 'text-green-500'
```

##### Default value — Override `defaultValue()` so cases without the attribute still return a value

[](#default-value--override-defaultvalue-so-cases-without-the-attribute-still-return-a-value)

You can also add a `defaultValue()` method to specify the value a case should have if it doesn't use the meta property. That way you can apply the attribute only on some cases and still get a configurable default value on all other cases.

#### `fromMeta()` — Get the first case matching a meta value or throw

[](#frommeta--get-the-first-case-matching-a-meta-value-or-throw)

```
TaskStatus::fromMeta(Color::make('green')); // TaskStatus::COMPLETED
TaskStatus::fromMeta(Color::make('blue')); // Error: ValueError
```

#### `tryFromMeta()` — Get the first case matching a meta value or null

[](#tryfrommeta--get-the-first-case-matching-a-meta-value-or-null)

```
TaskStatus::tryFromMeta(Color::make('green')); // TaskStatus::COMPLETED
TaskStatus::tryFromMeta(Color::make('blue')); // null
```

#### Included Meta Properties

[](#included-meta-properties)

The package ships with three ready-to-use meta properties:

##### Description

[](#description)

This attribute is a Single Value

##### Group

[](#group)

This attribute is Repeatable

##### Label

[](#label)

This attribute is a Single Value

#### Recommendation: use annotations and traits

[](#recommendation-use-annotations-and-traits)

For better IDE support, add `@method` annotations:

```
/**
 * @method string description()
 * @method string color()
 */
#[Meta(Description::class, Color::class)]
enum TaskStatus: int
{
    use Metadata;

    #[Description('Incomplete Task')] #[Color('red')]
    case INCOMPLETE = 0;

    #[Description('Completed Task')] #[Color('green')]
    case COMPLETED = 1;

    #[Description('Canceled Task')] #[Color('gray')]
    case CANCELED = 2;
}
```

If you reuse the same meta property across multiple enums, create a dedicated trait with the `@method` annotation.

### AsSelfAwareableEnum

[](#asselfawareableenum)

Introspect the nature of your enum at runtime.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-7)

```
use Phil\Enums\AsSelfAwareableEnumTrait;

enum TaskStatus: int
{
    use AsSelfAwareableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsSelfAwareableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### `isPure()` — Check if the enum is a pure enum (no backing type)

[](#ispure--check-if-the-enum-is-a-pure-enum-no-backing-type)

```
Role::isPure(); // true
TaskStatus::isPure(); // false
```

#### `isBacked()` — Check if the enum is backed

[](#isbacked--check-if-the-enum-is-backed)

```
TaskStatus::isBacked(); // true
Role::isBacked(); // false
```

#### `isBackedByInteger()` — Check if the enum is backed by `int`

[](#isbackedbyinteger--check-if-the-enum-is-backed-by-int)

```
TaskStatus::isBackedByInteger(); // true
```

#### `isBackedByString()` — Check if the enum is backed by `string`

[](#isbackedbystring--check-if-the-enum-is-backed-by-string)

```
TaskStatus::isBackedByString(); // false
```

### AsStringSelectableEnum

[](#asstringselectableenum)

Generate string representations of your enum options. This trait also includes `AsSelectableEnumTrait`.

#### Apply the trait on your enum

[](#apply-the-trait-on-your-enum-8)

```
use Phil\Enums\AsStringSelectableEnumTrait;

enum TaskStatus: int
{
    use AsStringSelectableEnumTrait;

    case INCOMPLETE = 0;
    case COMPLETED = 1;
    case CANCELED = 2;
}

enum Role
{
    use AsStringSelectableEnumTrait;

    case ADMINISTRATOR;
    case SUBSCRIBER;
    case GUEST;
}
```

#### `stringOptions()` — Generate a formatted string from enum cases

[](#stringoptions--generate-a-formatted-string-from-enum-cases)

```
// First argument is the callback, second argument is glue
TaskStatus::stringOptions(fn ($name, $value) => "$name => $value", ', '); // "INCOMPLETE => 0, COMPLETED => 1, CANCELED => 2"
```

For pure enums (non-backed), the name is used in place of `$value` (meaning that both `$name` and `$value` are the same).

Both arguments are optional. The default glue is `\n` and the default callback generates HTML `` tags:

```
// Incomplete
// Completed
// Canceled
TaskStatus::stringOptions(); // backed enum

// Administrator
// Subscriber
// Guest
Role::stringOptions(); // pure enum
```

PHPStan
-------

[](#phpstan)

To assist PHPStan when using invokable cases and metadata methods, include the PHPStan extension in your `phpstan.neon`:

```
includes:
  - ./vendor/ph-il/enums/extension.neon
```

Note

If you have [`phpstan/extension-installer`](https://github.com/phpstan/extension-installer) installed, the extension is included automatically.

Development
-----------

[](#development)

Run all checks locally:

```
castor ci:all
```

Code style will be automatically fixed by php-cs-fixer.

Todo
----

[](#todo)

- Version 0.3.0
    - Add operations
        - count
        - Add Filtering and Sorting
        - first
            - with or without filter via callback

License
-------

[](#license)

MIT. See [LICENSE](LICENSE) for details.

###  Health Score

37

—

LowBetter than 81% of packages

Maintenance85

Actively maintained with recent releases

Popularity7

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity42

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~28 days

Total

3

Last Release

79d ago

PHP version history (2 changes)0.1.0PHP ^8.1

0.2.0PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/ef4519e787b0e7b195d93d2f70f62fb1d811e06ef8b65389a24aed2e8abeb12b?d=identicon)[phil](/maintainers/phil)

---

Top Contributors

[![ph-il](https://avatars.githubusercontent.com/u/80009?v=4)](https://github.com/ph-il "ph-il (23 commits)")

---

Tags

enumenumeration

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan, Rector

Type Coverage Yes

### Embed Badge

![Health badge](/badges/ph-il-enums/health.svg)

```
[![Health](https://phpackages.com/badges/ph-il-enums/health.svg)](https://phpackages.com/packages/ph-il-enums)
```

###  Alternatives

[marc-mabe/php-enum

Simple and fast implementation of enumerations with native PHP

50458.3M110](/packages/marc-mabe-php-enum)[cerbero/enum

Zero-dependencies package to supercharge enum functionalities.

359235.5k2](/packages/cerbero-enum)[cerbero/laravel-enum

Laravel package to supercharge enum functionalities.

19097.9k](/packages/cerbero-laravel-enum)[emreyarligan/enum-concern

A PHP package for effortless Enumeration handling with Laravel Collections 📦 ✨

21262.1k2](/packages/emreyarligan-enum-concern)[rexlabs/enum

Enumeration (enum) implementation for PHP

47517.0k2](/packages/rexlabs-enum)[thunderer/platenum

PHP enum library

37147.4k](/packages/thunderer-platenum)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
