-
Notifications
You must be signed in to change notification settings - Fork 1
Add enum-polyfill package documentation #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
alexstandiford
wants to merge
1
commit into
main
Choose a base branch
from
docs/enum-polyfill-package
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,295 @@ | ||
| --- | ||
| id: enum-polyfill-introduction | ||
| slug: docs/packages/enum-polyfill/introduction | ||
| title: Enum Polyfill Package | ||
| doc_type: explanation | ||
| status: active | ||
| language: en | ||
| owner: docs-team | ||
| last_reviewed: 2026-01-25 | ||
| applies_to: ["all"] | ||
| canonical: true | ||
| summary: The enum-polyfill package provides PHP 8.1-style enum methods to regular classes using constants, enabling backward-compatible enum functionality. | ||
| llm_summary: > | ||
| phpnomad/enum-polyfill provides the Enum trait that gives PHP classes enum-like behavior using | ||
| class constants. It provides methods matching PHP 8.1's native enum API: cases(), from(), | ||
| tryFrom(), getValues(), and isValid(). The trait uses singleton pattern (via WithInstance) to | ||
| cache reflection results for performance. Classes using this trait define constants as enum | ||
| values and get automatic validation, iteration, and safe value retrieval. Commonly used for | ||
| HTTP methods, CRUD action types, session contexts, and other fixed sets of values. Works on | ||
| PHP 7.4+ and provides forward-compatible syntax for projects targeting older PHP versions. | ||
| questions_answered: | ||
| - What is the enum-polyfill package? | ||
| - How do I create enums in PHPNomad for older PHP versions? | ||
| - When should I use enum-polyfill vs native PHP enums? | ||
| audience: | ||
| - developers | ||
| - backend engineers | ||
| tags: | ||
| - enum | ||
| - polyfill | ||
| - trait | ||
| - backward-compatibility | ||
| llm_tags: | ||
| - enum-trait | ||
| - cases-method | ||
| - from-method | ||
| - tryFrom-method | ||
| - php-compatibility | ||
| keywords: | ||
| - phpnomad enum | ||
| - php enum polyfill | ||
| - enum trait php | ||
| - backward compatible enum | ||
| - php 7.4 enum | ||
| related: | ||
| - ../singleton/introduction | ||
| - ../auth/introduction | ||
| - ../http/introduction | ||
| see_also: | ||
| - ../cache/introduction | ||
| - ../rest/introduction | ||
| noindex: false | ||
| --- | ||
|
|
||
| # Enum Polyfill | ||
|
|
||
| `phpnomad/enum-polyfill` provides **PHP 8.1-style enum functionality for older PHP versions**. It consists of a single trait—`Enum`—that can be added to any class with constants to gain enum-like behavior. | ||
|
|
||
| At its core: | ||
|
|
||
| * **API compatibility** — Methods match PHP 8.1's native enum API (`cases()`, `from()`, `tryFrom()`) | ||
| * **Validation** — Check if values are valid enum members with `isValid()` | ||
| * **Performance** — Reflection results cached via singleton pattern | ||
| * **Zero migration path** — When upgrading to PHP 8.1+, switch to native enums with minimal changes | ||
|
|
||
| --- | ||
|
|
||
| ## Key ideas at a glance | ||
|
|
||
| | Component | Purpose | | ||
| |-----------|---------| | ||
| | [Enum trait](./traits/enum.md) | Add to any class with constants to get enum behavior | | ||
| | `cases()` / `getValues()` | Returns all possible enum values | | ||
| | `from($value)` | Gets value or throws exception if invalid | | ||
| | `tryFrom($value)` | Gets value or returns null if invalid | | ||
| | `isValid($value)` | Check if a value is a valid enum member | | ||
|
|
||
| --- | ||
|
|
||
| ## Why this package exists | ||
|
|
||
| PHP 8.1 introduced native enums, but many projects still support older PHP versions. Without a polyfill, developers must: | ||
|
|
||
| | Problem | Without enum-polyfill | With enum-polyfill | | ||
| |---------|----------------------|-------------------| | ||
| | Validation | Write custom validation per "enum" | `Status::isValid($value)` | | ||
| | Listing values | Manual array or reflection | `Status::cases()` | | ||
| | Safe retrieval | Custom try/catch everywhere | `Status::tryFrom($value)` | | ||
| | Migration path | Rewrite when upgrading PHP | Swap trait for native enum | | ||
|
|
||
| This package provides a **forward-compatible API** that mirrors PHP 8.1 enums, making future migration straightforward. | ||
|
|
||
| --- | ||
|
|
||
| ## Installation | ||
|
|
||
| ```bash | ||
| composer require phpnomad/enum-polyfill | ||
| ``` | ||
|
|
||
| **Requirements:** PHP 7.4+ | ||
|
|
||
| **Dependencies:** `phpnomad/singleton` | ||
|
|
||
| --- | ||
|
|
||
| ## Basic usage | ||
|
|
||
| Define a class with constants and add the trait: | ||
|
|
||
| ```php | ||
| use PHPNomad\Enum\Traits\Enum; | ||
|
|
||
| class Status | ||
| { | ||
| use Enum; | ||
|
|
||
| public const Active = 'active'; | ||
| public const Pending = 'pending'; | ||
| public const Inactive = 'inactive'; | ||
| } | ||
| ``` | ||
|
|
||
| Now use it like a PHP 8.1 enum: | ||
|
|
||
| ```php | ||
| // Get all possible values | ||
| $statuses = Status::cases(); | ||
| // ['active', 'pending', 'inactive'] | ||
|
|
||
| // Validate a value | ||
| if (Status::isValid($userInput)) { | ||
| // Safe to use | ||
| } | ||
|
|
||
| // Get value or null | ||
| $status = Status::tryFrom($userInput); | ||
| if ($status !== null) { | ||
| // Valid value | ||
| } | ||
|
|
||
| // Get value or throw exception | ||
| try { | ||
| $status = Status::from($userInput); | ||
| } catch (UnexpectedValueException $e) { | ||
| // Invalid value | ||
| } | ||
| ``` | ||
|
|
||
| See [Enum trait](./traits/enum.md) for complete API documentation. | ||
|
|
||
| --- | ||
|
|
||
| ## When to use this package | ||
|
|
||
| | Scenario | Recommendation | | ||
| |----------|---------------| | ||
| | PHP 7.4 / 8.0 project | Use enum-polyfill | | ||
| | PHP 8.1+ project | Consider native enums | | ||
| | Library supporting PHP 7.4+ | Use enum-polyfill for compatibility | | ||
| | Need custom enum methods | Use enum-polyfill (more flexible than native) | | ||
| | Strict type safety needed | Native PHP 8.1 enums are stronger | | ||
|
|
||
| ### Advantages over native enums | ||
|
|
||
| * Works on PHP 7.4+ | ||
| * Can add arbitrary methods to enum classes | ||
| * Constant values can be any type | ||
|
|
||
| ### Advantages of native enums | ||
|
|
||
| * True type safety (function accepts `Status`, not `string`) | ||
| * Better IDE support | ||
| * Pattern matching with `match` expressions | ||
| * Built into the language | ||
|
|
||
| --- | ||
|
|
||
| ## When NOT to use this package | ||
|
|
||
| ### You're on PHP 8.1+ exclusively | ||
|
|
||
| If you don't need to support older PHP versions, native enums are cleaner: | ||
|
|
||
| ```php | ||
| // Native PHP 8.1 enum | ||
| enum Status: string | ||
| { | ||
| case Active = 'active'; | ||
| case Pending = 'pending'; | ||
| case Inactive = 'inactive'; | ||
| } | ||
|
|
||
| // Type-safe function | ||
| function setStatus(Status $status): void | ||
| { | ||
| // $status is guaranteed to be a valid Status | ||
| } | ||
|
|
||
| setStatus(Status::Active); // OK | ||
| setStatus('active'); // Error - type mismatch | ||
| ``` | ||
|
|
||
| ### You need true type safety | ||
|
|
||
| The polyfill returns the constant values (strings, integers, etc.), not typed objects: | ||
|
|
||
| ```php | ||
| // With polyfill - no type safety | ||
| function setStatus(string $status): void | ||
| { | ||
| if (!Status::isValid($status)) { | ||
| throw new InvalidArgumentException(); | ||
| } | ||
| } | ||
|
|
||
| setStatus('typo'); // Compiles fine, fails at runtime | ||
| ``` | ||
|
|
||
| --- | ||
|
|
||
| ## Package contents | ||
|
|
||
| ### Traits | ||
|
|
||
| | Trait | Description | | ||
| |-------|-------------| | ||
| | [Enum](./traits/enum.md) | Provides enum-like behavior to classes with constants | | ||
|
|
||
| See [Traits Overview](./traits/introduction.md) for details. | ||
|
|
||
| --- | ||
|
|
||
| ## Migration to native enums | ||
|
|
||
| When you upgrade to PHP 8.1+, converting is straightforward: | ||
|
|
||
| ```php | ||
| // Before (polyfill) | ||
| use PHPNomad\Enum\Traits\Enum; | ||
|
|
||
| class Status | ||
| { | ||
| use Enum; | ||
|
|
||
| public const Active = 'active'; | ||
| public const Pending = 'pending'; | ||
| public const Inactive = 'inactive'; | ||
| } | ||
|
|
||
| $status = Status::from('active'); // 'active' | ||
| ``` | ||
|
|
||
| ```php | ||
| // After (native) | ||
| enum Status: string | ||
| { | ||
| case Active = 'active'; | ||
| case Pending = 'pending'; | ||
| case Inactive = 'inactive'; | ||
| } | ||
|
|
||
| $status = Status::from('active'); // Status::Active | ||
| ``` | ||
|
|
||
| The main difference: native enums return enum instances, while the polyfill returns the raw values. Update call sites accordingly. | ||
|
|
||
| --- | ||
|
|
||
| ## Relationship to other packages | ||
|
|
||
| ### Dependencies | ||
|
|
||
| | Package | Relationship | | ||
| |---------|-------------| | ||
| | [singleton](../singleton/introduction.md) | Uses `WithInstance` trait for caching | | ||
|
|
||
| ### Packages that use enum-polyfill | ||
|
|
||
| | Package | How it uses enum-polyfill | | ||
| |---------|--------------------------| | ||
| | [auth](../auth/introduction.md) | `ActionTypes`, `SessionContexts` enums | | ||
| | [http](../http/introduction.md) | `Method` enum for HTTP verbs | | ||
| | [cache](../cache/introduction.md) | `Operation` enum for CRUD operations | | ||
| | [rest](../rest/introduction.md) | `BasicTypes` enum | | ||
| | wordpress-plugin | Various status and type enums | | ||
|
|
||
| --- | ||
|
|
||
| ## Next steps | ||
|
|
||
| * **[Enum Trait](./traits/enum.md)** — Complete API reference | ||
| * **[Singleton Package](../singleton/introduction.md)** — Understand the caching mechanism | ||
| * **[HTTP Package](../http/introduction.md)** — See Method enum in action | ||
| * **[Auth Package](../auth/introduction.md)** — See ActionTypes enum | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These related/see_also entries point at
../singleton,../auth,../http, and../cachedocs that are not present anywhere underpublic/docs/packages, so the rendered links will 404 in the published site. Either add those package docs or remove/update these references so the navigation doesn’t include dead links.Useful? React with 👍 / 👎.