Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/greg0ire/enum
A workaround for the missing php enum type
https://github.com/greg0ire/enum
enum php symfony symfony-validator twig
Last synced: 19 days ago
JSON representation
A workaround for the missing php enum type
- Host: GitHub
- URL: https://github.com/greg0ire/enum
- Owner: greg0ire
- License: other
- Created: 2014-06-17T13:36:32.000Z (over 10 years ago)
- Default Branch: stable
- Last Pushed: 2023-05-25T09:56:21.000Z (over 1 year ago)
- Last Synced: 2024-10-13T04:11:45.166Z (about 1 month ago)
- Topics: enum, php, symfony, symfony-validator, twig
- Language: PHP
- Size: 261 KB
- Stars: 46
- Watchers: 4
- Forks: 4
- Open Issues: 2
-
Metadata Files:
- Readme: README.md
- Contributing: CONTRIBUTING.md
- License: LICENSE
Awesome Lists containing this project
README
# Enums
This package holds a simple class that may be used as an ancestor for your
enum classes.[![Build Status][3]](https://travis-ci.org/greg0ire/enum)
## Installation
composer require greg0ire/enum
## Usage
### Basic usage
Extend the `Greg0ire\Enum\AbstractEnum`, define your enum key values as constants,
and Bob's your uncle. You can make the class abstract or final, as you see fit.```php
use Greg0ire\Enum\AbstractEnum;final class DaysOfWeek extends AbstractEnum {
const Sunday = 0;
const Monday = 1;
const Tuesday = 2;
const Wednesday = 3;
const Thursday = 4;
const Friday = 5;
const Saturday = 6;
}
```Then, you may use the DaysOfWeek class for input validation:
```php
DaysOfWeek::isValidName('Humpday'); // false
DaysOfWeek::isValidName('Monday'); // true
DaysOfWeek::isValidName('monday'); // false
DaysOfWeek::isValidName(0); // falseDaysOfWeek::isValidValue(0); // true
DaysOfWeek::isValidValue(5); // true
DaysOfWeek::isValidValue(7); // false
DaysOfWeek::isValidValue('Friday'); // false
```Both methods have an `assert*` counterpart that will throw a
`Greg0ire\Enum\Exception\InvalidEnumValue` exception:```
DaysOfWeek::assertValidName(0); // InvalidEnumName
DaysOfWeek::assertValidValue('Friday'); // InvalidEnumValue
```Additionally, you may get all the constants in your class as a hash:
```php
DaysOfWeek::getConstants();
DaysOfWeek::getConstants('strtolower'); // Will combine your values with `DaysOfWeek::getKeys($callback)`.
DaysOfWeek::getConstants('strtolower', true); // Values combine with `DaysOfWeek::getClassPrefixedKeys($callback)`.
DaysOfWeek::getConstants('strtolower', true, '.'); // Same with `DaysOfWeek::getClassPrefixedKeys($callback, $separator)`.
```You may also get all the keys in your class as an array:
```php
DaysOfWeek::getKeys();
DaysOfWeek::getKeys('strtolower'); // Will call `array_map` with the given callback.
```Or the key with the enum class prefix:
```php
DaysOfWeek::getClassPrefixedKeys();
DaysOfWeek::getClassPrefixedKeys('strtolower'); // Will call `array_map` with the given callback.
DaysOfWeek::getClassPrefixedKeys('strtolower', '.'); // Replace the namespace separator ('_' by default).
```If you would like to get the keys from a value:
```php
$key = DaysOfWeek::getKeysFromValue(1); // Monday will be assigned to $key
```If you have many keys with the same value you will get an array, and a value otherwise.
### Advanced usage
If you need to get the constants from a class you cannot modify, or from an
interface, or even from several classes / interfaces, you may override
`AbstractEnum::getEnumTypes()`.For example, if you have the following class and interface :
```php
namespace Vendor\Namespace;class ClassFromAVendor
{
const SOMETHING = 'something';
const SOMETHING_ELSE = 'something_else';
}
``````php
namespace My\Namespace;interface SomeInterface
{
const ANOTHER_CONST = 'another_const';
}
```You can get all three constants by creating this Enum :
```php
use Greg0ire\Enum\AbstractEnum;
use My\Namespace\SomeInterface;
use Vendor\Namespace\ClassFromAVendor;final class MyEnum extends AbstractEnum
{
protected static function getEnumTypes()
{
return [ClassFromAVendor::class, SomeInterface::class];
}
}
```Alternatively, you can specify a prefix for each type to avoid getting FQCNs in
the hash keys.```php
use Greg0ire\Enum\AbstractEnum;
use My\Namespace\SomeInterface;
use Vendor\Namespace\ClassFromAVendor;final class MyEnum extends AbstractEnum
{
protected static function getEnumTypes()
{
return [
'prefix1' => ClassFromAVendor::class,
'prefix2' => SomeInterface::class,
];
}
}
```### Get label from a service
If you want to get the constant label behind an enum value, you can instantiate
the `GetLabel` class and invoke it.```php
use Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel;$label = new GetLabel();
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class);
```To enable translation, require the `symfony/translation` component
and pass a `Symfony\Contracts\Translation\TranslationInterface` instance on the
`GetLabel` constructor```php
use Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel;
use Symfony\Contracts\Translation\TranslationInterface;$label = new GetLabel($translator);
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class);
```If you're using Symfony, alias the service and simply inject it.
If translations are enabled, the `TranslatorInterface` will be automatically injected.```yaml
services:
# ...
Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel: "@greg0ire_enum.symfony.translator.get_label"
``````php
public function index(GetLabel $label)
{
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class);
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class, 'another_domain'); // Change the translation domain
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false); // Disable translation. In this case the class prefix wont be added
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false, true); // Disable translation but keep class prefix
$label(Your\Enum\Class::VALUE, Your\Enum\Class::class, false, true, '.'); // Disable translation but keep class prefix with a custom separator
}
```### Integration with other libraries
`greg0ire/enum` integrates with other libraries. The list is available in the
`suggest` section of the Composer dependency manifest.#### Symfony validator
This package provides a "ready to use" symfony validator.
You have to require the `symfony/validator` package to get it working.```php
use Greg0ire\Enum\Bridge\Symfony\Validator\Constraint\Enum;
use Symfony\Component\Validator\Validation;
use Your\Namespace\EnumClass;$validator = Validation::createValidator();
$violations = $validator->validateValue(42, new Enum(EnumClass::class));
// You can also show the constants keys on the error message:
$violations = $validator->validateValue(42, new Enum(['class' => EnumClass::class, 'showKeys' => true]));
// Enum constraint inherits from Choice constraint. You can use inherited options too:
$violations = $validator->validateValue(42, new Enum(['class' => EnumClass::class, 'strict' => true]));
```Another example with annotations:
```php
use Doctrine\Common\Annotations\AnnotationRegistry;
use Greg0ire\Enum\Bridge\Symfony\Validator\Constraint\Enum as EnumAssert;
use Symfony\Component\Validator\Validation;class MyClass
{
/**
* @EnumAssert("Your\Namespace\EnumClass")
*/
private $dummy;public function __construct($dummy)
{
$this->dummy = $dummy
}
}AnnotationRegistry::registerLoader('class_exists');
$validator = Validation::createValidatorBuilder()
->enableAnnotationMapping()
->getValidator();$object = new MyClass(42);
$violations = $validator->validate($object);
```Note: You will have to get `doctrine/annotations` and `doctrine/cache` packages to get it working.
#### Symfony form
This package provides a "ready to use" symfony form type.
You have to require the `symfony/form` package to get it working.```php
use Greg0ire\Enum\Bridge\Symfony\Form\Type\EnumType;
use Symfony\Component\Form\Forms;
use Your\Namespace\EnumClass;$formFactory = Forms::createFormFactory();
$view = $this->factory->create(EnumType::class, null, array(
'class' => EnumClass::class,
))->createView();
```#### Twig extension
This package comes with an `EnumExtension` Twig class. It contains a filter and some functions.
You have to require the `twig/twig` package to get it working.##### Filter
The `enum_label` filter will try to return the constant label corresponding to the given value.
This filter relies on the `Greg0ire\Enum\Bridge\Symfony\Translator\GetLabel` service.
It will try to translate it if possible. To enable translation, require the `symfony/translation` component
and pass a `Symfony\Contracts\Translation\TranslationInterface` instance on the `GetLabel` constructor.
`GetLabel` instance will be injected on the `EnumExtension` constructor.If translation is not available, you will have the default label with class prefixing.
Usage:
```twig
{{ value|enum_label('Your\\Enum\\Class') }}
{{ value|enum_label('Your\\Enum\\Class', 'another_domain') }} {# Change the translation domain #}
{{ value|enum_label('Your\\Enum\\Class', false) }} {# Disable translation. In this case the class prefix wont be added #}
{{ value|enum_label('Your\\Enum\\Class', false, true) }} {# Disable translation but keep class prefix #}
{{ value|enum_label('Your\\Enum\\Class', false, true, '.') }} {# Disable translation but keep class prefix with a custom separator #}
```##### Functions
The 3 available twig functions are ports of some `AbstractEnum` methods that can be useful in a twig template:
* `enum_get_constants` => `AbstractEnum::getConstants`
* `enum_get_keys` => `AbstractEnum::getKeys`
* `enum_get_class_prefixed_keys` => `AbstractEnum::getClassPrefixedKeys`The arguments are exactly the same except you have to specify the targeted class first (as `enum_label` filter).
Here is a concrete example with `enum_get_constants` function:
```twig
{% for enum_key, enum_value in enum_get_constants('Your\\Enum\\Class') %}
{{ enum_key }} -> {{ enum_value }}
{% endfor %}
```##### Twig extension as a service
On Symfony projects, the extension can be autoloaded.
First, you have to require the `symfony/framework-bundle` and `symfony/twig-bundle` packages, or use Symfony fullstack.Then, register the bundle in the kernel of your application:
``` php
// app/AppKernel.phppublic function registerBundles()
{
$bundles = [
// ...
new Greg0ire\Enum\Bridge\Symfony\Bundle\Greg0ireEnumBundle(),
];// ...
return $bundles
}
```That's all. You can now directly use the filter.
## Contributing
see [CONTRIBUTING.md][1]
## Credits
This is a shameless rip-off of [this Stack Overflow answer][0], with one
modification: the `getConstants` method has been made public so that it is
available for building choice widgets, for instance. If you want to give credit
to someone for this, give it to [Brian Cline][2][0]: http://stackoverflow.com/a/254543/353612
[1]: ./CONTRIBUTING.md
[2]: http://stackoverflow.com/users/32536/brian-cline
[3]: https://travis-ci.org/greg0ire/enum.svg?branch=master