{"id":21215334,"url":"https://github.com/zlikavac32/php-enum","last_synced_at":"2025-07-10T11:31:23.903Z","repository":{"id":54892802,"uuid":"108051557","full_name":"zlikavac32/php-enum","owner":"zlikavac32","description":"Better PHP enum support","archived":false,"fork":false,"pushed_at":"2022-11-15T11:34:28.000Z","size":114,"stargazers_count":23,"open_issues_count":0,"forks_count":1,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-09-24T22:23:21.800Z","etag":null,"topics":["enum","enumeration","php","php-enum"],"latest_commit_sha":null,"homepage":null,"language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zlikavac32.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-10-23T23:22:25.000Z","updated_at":"2022-11-15T11:33:06.000Z","dependencies_parsed_at":"2022-08-14T06:00:22.227Z","dependency_job_id":null,"html_url":"https://github.com/zlikavac32/php-enum","commit_stats":null,"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fphp-enum","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fphp-enum/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fphp-enum/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zlikavac32%2Fphp-enum/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zlikavac32","download_url":"https://codeload.github.com/zlikavac32/php-enum/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225634146,"owners_count":17500108,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["enum","enumeration","php","php-enum"],"created_at":"2024-11-20T21:37:09.153Z","updated_at":"2024-11-20T21:37:09.749Z","avatar_url":"https://github.com/zlikavac32.png","language":"PHP","readme":"# PHP Enum\n\n![Build Status](https://github.com/zlikavac32/php-enum/workflows/PHP%20Enum/badge.svg?branch=master) [![Latest Stable Version](https://poser.pugx.org/zlikavac32/php-enum/v/stable)](https://packagist.org/packages/zlikavac32/php-enum) [![License](https://poser.pugx.org/zlikavac32/php-enum/license)](https://packagist.org/packages/zlikavac32/php-enum)\n\nThis library aims to make your everyday enumeration use in PHP easier.\n\n## Table of contents\n\n1. [What are enums and when to use them?](#what-are-enums-and-when-to-use-them)\n1. [Installation](#installation)\n1. [Features](#features)\n    1. [Type-hinting](#type-hinting)\n    1. [Polymorphism](#polymorphism)\n    1. [Identity check](#identity-check)\n1. [API](#api)\n    1. [Class methods](#class-methods)\n    1. [Object methods](#object-methods)\n    1. [Assert functions](#assert-functions)\n1. [Usage](#usage)\n    1. [UnhandledEnumException](#unhadledenumexception)\n1. [Restrictions](#restrictions)\n    1. [No serialisation](#no-serialisation)\n    1. [No cloning](#no-cloning)\n    1. [Reserved methods](#reserved-methods)\n1. [Limitations](#limitations)\n1. [Rule of thumb](#rule-of-thumb)\n1. [Examples](#examples)\n1. [Reasoning behind this library](#reasoning-behind-this-library)\n\n## What are enums and when to use them?\n\nTo reference [Wikipedia](http://wikipedia.org/wiki/Enumerated_type):\n\u003e In computer programming, an enumerated type (also called enumeration, enum, or factor in the R programming language, and a categorical variable in statistics) is a data type consisting of a set of named values called elements, members, enumeral, or enumerators of the type. [...] In other words, an enumerated type has values that are different from each other, and that can be compared and assigned, but are not specified by the programmer as having any particular concrete representation in the computer's memory; compilers and interpreters can represent them arbitrarily.\n\nYou can think of enums as constants on steroids and the main benefit of using enums is that you hide internal representation or in other words, enums are types themselves. Constants on the other hand inherit type of the assigned value. On top of that, this implementation offers polymorphic behaviour (inspired by [Java Enum](https://docs.oracle.com/javase/8/docs/api/java/lang/Enum.html)).\n\nThat being said, if you want to logically group similar items, use enums and for other things use constants. By using enums you can type-hint arguments and return values and delegate various checks to the PHP engine.\n\n## Installation\n\nRecommended installation is through Composer.\n\n```\ncomposer require zlikavac32/php-enum\n```\n\n## Features\n\nCustom enum implementations (emulations) are nothing new in the PHP world since PHP lacks a native enum support. This library aims to provide correct enumeration support in PHP.\n\n### Type-hinting\n\nYou can type-hint your arguments and return values just like with any other class (`function getNextDay(WeekDay $day): Day`). This, sort of (check [Limitations](#limitations)), guarantees that you'll always get valid enumeration object.\n\n### Polymorphism\n\nBehind the curtain, every enumeration is an instance of the defined enumeration class. That enables you to define your own constructor, override some methods or even define abstract methods that are later implemented in different enum variations.\n\n### Identity check\n\nEvery call to enum object guarantees to return same instance every time it is called. That way you can use `===` to check whether instances are the same or not.\n\n## API\n\nMain class is `\\Zlikavac32\\ZEnum\\ZEnum` which serves as base enum (I'd rather have `enum` keywords, but life isn't perfect). You have to extend it and provide list of static methods in the class PHPDoc comment. Check the [Usage](#usage) section to see a real example.\n\nThis class also exposes few public static and non static methods which are listed bellow.\n\n### Class methods\n\n- `final valueOf(string $name): static` - returns enum object identified by the name or throws an exception if none is found\n- `final contains(string $name): bool` - returns `true` if enum object identified by the name `$name` exists, `false` otherwise\n- `final values(): static[]` - returns all of the defined enum objects in order they were defined\n- `iterator(): Iterator\u003cstatic\u003e` - returns iterator object with all of the defined enum objects in order they were defined\n\n### Object methods\n\n- `__toString(): string` - returns default string representation which is the enum name itself\n- `jsonSerialize(): mixed` - defaults to element name\n- `final name(): string` - returns enum object name\n- `final ordinal(): int` - returns ordinal number of that enum object (it's position in the collection) starting from 0\n- `final isAnyOf(Enum ...$enums): bool` - returns `true` if enum object is in the `$enums` list, `false` otherwise\n\nOther methods serve as a way to restrict inconsistent behaviour, for example, to have two distinct objects of the same enum name. Check the [Restrictions](#restrictions) section for more info.\n\n### Assert functions\n\nIn `src/functions.php` are some helper function that could help you asserting certain input. Every function throws `\\LogicException` on failed assertion. You can check the source for documentation, here is just a list of them:\n\n- `assertFqnIsEnumClass(string $fqn): void`\n- `assertEnumClassAdheresConstraints(string $fqn): void`\n- `assertNoParentHasEnumerateMethodForClass(string $fqn): void`\n- `assertNoParentHasPHPDocMethodForClass(string $fqn): void`\n- `assertValidNamePattern(string $name): void`\n- `assertEnumClassIsAbstract(string $fqn): void`\n- `assertValidEnumCollection(string $class, array $enumCollection, string $enumClassFqn): void`\n- `assertElementNameIsString(string $class, $name): void`\n- `assertValidEnumElementObjectType(string $class, $object, string $enumClassFqn): void`\n\n## Usage\n\nCreate an abstract class that will represent your enum and let it extend `\\Zlikavac32\\ZEnum\\ZEnum`.\n\nYou must list static methods in the class PHPDoc comment. Method names are used as enum names.\n\n```php\n/**\n * @method static YesNo YES\n * @method static YesNo NO\n */\nabstract class YesNo extends \\Zlikavac32\\ZEnum\\ZEnum\n{\n\n}\n```\n\nOnce you have your enum class defined, you can access each defined enum object by calling `YourEnumClass::YOUR_ENUM_NAME()` or in the example above, `YesNo::YES()` and `YesNo::NO()`.\n\nOther suggestion is to use constant like convention when defining enum name where you use upper-cased letters and underscore as a separator.\n\nEvery call to the same enum will return that same object so you can safely use identity operator.\n\nIt's also possible to manually instantiate enum objects and return them as a map (instead of a list of names).\n\n```php\n/**\n * @method static YesNo YES\n * @method static YesNo NO\n */\nabstract class YesNo extends \\Zlikavac32\\ZEnum\\ZEnum\n{\n    protected static function enumerate(): array\n    {\n        return [\n            'YES' =\u003e new class extends YesNo {},\n            'NO' =\u003e new class extends YesNo {}\n        ];\n    }\n}\n```\n\nNote that every enum name listed in the PHPDoc comment must exist as a key in the enumerate method with a valid enum object as a value.\n\n### UnhandledEnumException\n\nIt would be nice if we'd get notified when we have an unhandled branch when new enum names are added. This is not available without a bit of manual work.\n\nA convenient `\\Zlikavac32\\ZEnum\\UnhandledEnumException` is provided to make that manual work a bit easier. Easier in a sense that we get nice error message.\n\nIt's intended to be thrown in the default case when checking every enum name.\n\n```php\nswitch ($enum) {\n    case YesNo::YES():\n        // do something\n    case YesNo::NO():\n        // do something else\n    default:\n        throw new UnhandledEnumException($enum);\n}\n```\n\n### More than one parent\n\nIt is possible to have more than one class between defining enum class and `\\Zlikavac32\\ZEnum\\ZEnum` class with a few restrictions (check [Restrictions regarding inheritance](#restrictions-regarding-inheritance)).\n\nTo see an example, open [examples/hashable_enum.php](examples/hashable_enum.php).\n\n## Restrictions\n\nTo mitigate wrong usage and sleepless nights in debugging, some restrictions are placed. They exist not because I want them to, but to serve as an early warning that something could go wrong in the long run. If you try really hard, you can still avoid them but then what's the purpose of this library to you?\n\n### No serialisation\n\nIn order to try to avoid misuse as much as possible, you can not serialize/unserialize enumeration objects. With normal library usage, this preserves identity check which could unintentionally be broken.\n\n### No cloning\n\nThe reasoning behind this is the same as with serialisation.\n\n### Restrictions regarding inheritance\n\n- no class in between can list methods in PHPDoc comment\n- no class in between can define `enumerate` method\n- every class in the chain must be defined as abstract\n- defining enum class must be first parent for the concrete enum object\n\n### Reserved methods\n\nNone of the public methods in `\\Zlikavac32\\ZEnum\\ZEnum` can be used as an enum name. Check the [API](#api) section for more details.\n\n## Limitations\n\nAs with any emulation, there are some limitations. Main limitation is that this library can not guarantee that every object is one of the valid enum instances. If you try really hard to find an edge case, you'll succeed, but this is not the idea because this can't be fixed in the first place. If a language does not put some restrictions, user land implementations can hardly do that. \n\nSince you can always extend existing enum, you can send it somewhere where valid enum is expected and I don't think that for now there is a way to restrict that. Non final class is needed to make enum objects and therefore, no restrictions that can be done. Even if they could, they could be avoided in a same way. \n\nOn the other hand, you can never alter existing enums which is one of the goals. \n\nOther limitation is that everything is done during runtime so some static analysis my report issues or some compiler checks may not be performed that would otherwise be performed if PHP had native support. To combat that, you can hint methods in doc-block comments.\n\n## Rule of thumb\n\nUsed correctly, this library should make your life easier and your code more readable and more sense. Only thing you should avoid doing is extending (and constructing) your enum class outside of the `enumerate()` method. \n\nDon't make your enums complex. If you need a service for your enum to work, you may not need an enum or that logic does not belong here.\n\nThis is not a solution to the every problem. If you have a group of items that semantically belong together and have a common \"type\" like, `Gender` or `WorldSide`, make them an enum. If your items contain arbitrary values that tend to change like `WORKER_WAIT_TIME`, let them be constants. They mean different things.\n\nSo to recap, enums carry a meaning with them, constants don't.\n\n## Examples\n\nYou can see more examples with code comments in [examples](/examples).\n\n## Reasoning behind this library\n\nI find this way quite intuitive and a good enum direction. You can misuse everything if you want to. This does not mean that you should not use this library. It means that this will make your easier if you use it with these limitations on your mind.\n\nEnums are not just groups of constants, they are types themselves and can exhibit polymorphic behaviour. This is what this library aims to provide. Use it with care and it should be more than helpful.\n\nFinal goal is to see something similar as a native PHP enum implementation, but for now, one can just dream, right?\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlikavac32%2Fphp-enum","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzlikavac32%2Fphp-enum","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzlikavac32%2Fphp-enum/lists"}