All Projects → Elao → Phpenums

Elao / Phpenums

Licence: mit
🔩 Provides enumerations for PHP & frameworks integrations

Programming Languages

enum
40 projects

Projects that are alternatives of or similar to Phpenums

Bugbounty Starter Notes
bug bounty hunters starter notes
Stars: ✭ 85 (-56.19%)
Mutual labels:  hacktoberfest, enumeration
Paraunit
Run PHPUnit tests in parallel
Stars: ✭ 104 (-46.39%)
Mutual labels:  hacktoberfest, symfony
Platform
Shopware 6 is an open source eCommerce platform realised by the ideas and the spirit of its community.
Stars: ✭ 1,267 (+553.09%)
Mutual labels:  hacktoberfest, symfony
Forkcms
Fork is an easy to use open source CMS using Symfony Components.
Stars: ✭ 1,112 (+473.2%)
Mutual labels:  hacktoberfest, symfony
Symfony Docs
The Symfony documentation
Stars: ✭ 1,924 (+891.75%)
Mutual labels:  hacktoberfest, symfony
Dms Filter Bundle
Provides a FilterService for Symfony to allow users to implement input filtering in entities using Annotations
Stars: ✭ 74 (-61.86%)
Mutual labels:  hacktoberfest, symfony
Feroxbuster
A fast, simple, recursive content discovery tool written in Rust.
Stars: ✭ 1,314 (+577.32%)
Mutual labels:  hacktoberfest, enumeration
Symfony Docker
A Docker-based installer and runtime for Symfony. Install: download and `docker-compose up`.
Stars: ✭ 732 (+277.32%)
Mutual labels:  hacktoberfest, symfony
Core
The server component of API Platform: hypermedia and GraphQL APIs in minutes
Stars: ✭ 2,004 (+932.99%)
Mutual labels:  hacktoberfest, symfony
Nosqlmap
Automated NoSQL database enumeration and web application exploitation tool.
Stars: ✭ 1,928 (+893.81%)
Mutual labels:  hacktoberfest, enumeration
Fosoauthserverbundle
A server side OAuth2 Bundle for Symfony
Stars: ✭ 1,068 (+450.52%)
Mutual labels:  hacktoberfest, symfony
Sylius Standard
Open Source eCommerce Application on top of Symfony
Stars: ✭ 165 (-14.95%)
Mutual labels:  hacktoberfest, symfony
Sylius
Open Source eCommerce Platform on Symfony
Stars: ✭ 6,598 (+3301.03%)
Mutual labels:  hacktoberfest, symfony
Pugxautocompleterbundle
Add an autocomplete field to your Symfony forms
Stars: ✭ 83 (-57.22%)
Mutual labels:  hacktoberfest, symfony
Symfony 5 Es Cqrs Boilerplate
Symfony 5 DDD ES CQRS backend boilerplate
Stars: ✭ 759 (+291.24%)
Mutual labels:  hacktoberfest, symfony
Rymfony
A work-in-progress CLI tool built in Rust to mimic the Symfony CLI binary
Stars: ✭ 89 (-54.12%)
Mutual labels:  hacktoberfest, symfony
Wallabag
wallabag is a self hostable application for saving web pages: Save and classify articles. Read them later. Freely.
Stars: ✭ 6,392 (+3194.85%)
Mutual labels:  hacktoberfest, symfony
Symfony
The Symfony PHP framework
Stars: ✭ 26,220 (+13415.46%)
Mutual labels:  hacktoberfest, symfony
Eventum
Eventum Issue Tracking System
Stars: ✭ 120 (-38.14%)
Mutual labels:  hacktoberfest, symfony
Enqueue Dev
Message Queue, Job Queue, Broadcasting, WebSockets packages for PHP, Symfony, Laravel, Magento. DEVELOPMENT REPOSITORY - provided by Forma-Pro
Stars: ✭ 1,977 (+919.07%)
Mutual labels:  hacktoberfest, symfony

Elao Enumerations

Latest Stable Version Total Downloads Monthly Downloads Build Status Coveralls Scrutinizer Code Quality php

This project aims to provide the missing PHP enumerations support:

<?php

final class Gender extends Enum
{
    use AutoDiscoveredValuesTrait;
    
    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';
}

It will leverage integration of the main PHP frameworks and also provide bridges with other libraries when relevant.

Table of Contents

Why?

An enumeration is a strong data type providing identifiers you'll use in your application. Such a type allows libraries and framework integration, which this package will provide when relevant.

Show more about enums

An enumeration is a data type, enclosing a single value from a predictable set of members (enumerators). Each enumerator name is a single identifier, materialized by a PHP constant.

Using an enum class provides many benefits:

  • Brings visibility in your code
  • Provides Type Hinting when using the enum class
  • Centralizes enumeration logic within a class
  • Defines utility methods or minor logic owned by your enumeration
  • Helps to describe how to read, serialize, export [, ...] an enumeration
  • Allows common libraries and frameworks integrations.

Enumerations are not options and are not meant to replace constants. Designing an enum type should be done by keeping your domain in mind, and should convey a strong meaning on your application logic.

Wrong use-cases:

  • A set of options used by a library or a method.
  • An unpredictable set of elements.
  • An non-reusable set of elements inside the application.
  • Long sets of elements (languages, locales, currencies, ...)
  • Holding variable data inside the enum type (use an intermediate value object holding the data and the enum instance instead).

Valid use-cases:

  • Gender, civility, predictable roles and permissions, ...
  • A set of supported nodes in an importer, or a set of predefined attributes.
  • In a game: predefined actions, movement directions, character classes, weapon types, ...
  • Any other set of restricted elements.

Why another library ?

  • myclabs/php-enum provides a base enum implementation as a class, inspired from \SplEnum. However, it doesn't provide as many features nor integrations as we wish to.
  • commerceguys/enum only acts as a utility class, but does not intend to instantiate enumerations. Hence, it doesn't allow as many features nor integrations with third-party libraries and frameworks. Manipulating enums as objects is also one of the first motivations of this project.
  • yethee/BiplaneEnumBundle is the first library we got inspiration from. But it was designed as a Symfony Bundle, whereas we opted for a component first approach. Integrations are then provided in a dedicated Bridge namespace and are not restricted to Symfony.

Finally, we used to create similar classes from scratch in some projects lately.
Providing our own package inspired from the best ones, on which we'll apply our own philosophy looks a better way to go.

Features

  • Base implementation for simple, readable and flagged (bitmask) enumerations based on the BiplaneEnumBundle ones.
  • Symfony Form component integration with form types.
  • Symfony Serializer component integration with a normalizer class.
  • Symfony Validator component integration with an enum constraint.
  • Symfony VarDumper component integration with a dedicated caster.
  • Symfony HttpKernel component integration with an enum resolver for controller arguments.
  • Doctrine DBAL integration with abstract classes in order to persist your enumeration in database.
  • Faker enum provider to generate random enum instances.
  • An API Platform OpenApi/Swagger type for documentation generation.
  • JavaScript enums code generation.

Installation

$ composer require elao/enum

In a Symfony app using Flex, the Elao\Enum\Bridge\Symfony\Bundle\ElaoEnumBundle bundle should be registered automatically.

Usage

Declare your own enumeration by creating a class extending Elao\Enum\Enum:

<?php

use Elao\Enum\Enum;

final class Gender extends Enum
{
    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';

    public static function values(): array
    {
        return [
            self::UNKNOWN, 
            self::MALE, 
            self::FEMALE
        ];
    }
}

Get an instance of your enum type:

<?php
$enum = Gender::get(Gender::Male);

You can easily retrieve the enumeration's value by using $enum->getValue();

📝 Enum values are supposed to be integers or strings.

📝 It's recommended to make your enums classes final, because it won't make sense to extend them in most situations (unless you're creating a new base enum type), and you won't need to mock an enum type.

💡 You can also use the AutoDiscoveredValuesTrait to automagically guess values from the constants defined in your enum, so you don't have to implement EnumInterface::values() yourself:

<?php

use Elao\Enum\Enum;
use Elao\Enum\AutoDiscoveredValuesTrait;

final class Gender extends Enum
{
    use AutoDiscoveredValuesTrait;
    
    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';
}

The AutoDiscoveredValuesTrait also allows you to discover values from other classes. Given the following class holding constants:

<?php

namespace MangoPay;

final class EventType
{
    public const KycCreated = "KYC_CREATED";
    public const KycSucceeded = "KYC_SUCCEEDED";
    public const KycFailed = "KYC_FAILED";
}

You can create an enum from it by overriding the AutoDiscoveredValuesTrait::getDiscoveredClasses() method:

<?php

namespace App\Enum;

use Elao\Enum\Enum;
use Elao\Enum\AutoDiscoveredValuesTrait;

final class MangoPayEventType extends Enum
{
    use AutoDiscoveredValuesTrait;

    protected static function getDiscoveredClasses(): array
    {
        return [self::class, MangoPay\EventType::class];
    }
}

# Usage:
MangoPayEventType::get(MangoPay\EventType::KycCreated);

Readable enums

Sometimes, enums may be displayed to the user, or exported in a human readable way.
Hence comes the ReadableEnum:

<?php

use Elao\Enum\ReadableEnum;

final class Gender extends ReadableEnum
{
    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';

    public static function values(): array
    {
        return [
            self::UNKNOWN,
            self::MALE,
            self::FEMALE,
        ];
    }

    public static function readables(): array
    {
        return [
            self::UNKNOWN => 'Unknown',
            self::MALE => 'Male',
            self::FEMALE => 'Female',
        ];
    }
}

The following snippet shows how to render the human readable value of an enum:

<?php
$enum = Gender::get(Gender::Male); 
$enum->getReadable(); // returns 'Male'
(string) $enum; // returns 'Male'

If you're using a translation library, you can also simply return translation keys from the ReadableEnumInterface::readables() method:

<?php

use Elao\Enum\ReadableEnum;

final class Gender extends ReadableEnum
{
    // ...
    
    public static function readables(): array
    {
        return [
            self::UNKNOWN => 'enum.gender.unknown',
            self::MALE => 'enum.gender.male',
            self::FEMALE => 'enum.gender.female',
        ];
    }
}

Using Symfony's translation component:

 # translations/messages.en.yaml
 enum.gender.unknown: 'Unknown'
 enum.gender.male: 'Male'
 enum.gender.female: 'Female'
<?php
$enum = Gender::get(Gender::MALE);
// get translator instance...
$translator->trans($enum); // returns 'Male'

If you want to extract and update the translations automatically using the translation extractor command you can use the provided custom extractor:

# config/packages/elao_enum.yaml
elao_enum:
    translation_extractor:
        # mandatory, provides the namespace to path mappings where to search for ReadableEnum (will also search subdirectories)
        paths:
            App\Enum: '%kernel.project_dir%/src/Enum'
        domain: messages # optional, specifies the domain for translations
        filename_pattern: '*.php' # optional, specifies the filename pattern when searching in folders
        ignore: [] # optional, specifies the folders/files to ignore (eg. '%kernel.project_dir%/src/Enum/Ignore/*') 

Choice enums

Choice enums are a more opinionated version of readable enums. Using the ChoiceEnumTrait in your enum, you'll only need to implement a choices() method instead of both EnumInterface::values() and ReadableEnum::readables() ones:

<?php

use Elao\Enum\ChoiceEnumTrait;
use Elao\Enum\ReadableEnum;

final class Gender extends ReadableEnum
{
    use ChoiceEnumTrait;

    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';

    public static function choices(): array
    {
        return [
            self::UNKNOWN => 'Unknown',
            self::MALE => 'Male',
            self::FEMALE => 'Female',
        ];
    }
}

It is convenient as it implements the two values & readables methods for you, which means you don't have to keep it in sync anymore.

The SimpleChoiceEnum base class allows you to benefit from both choice enums conveniency along with enumerated values auto-discoverability through public constants:

<?php

use Elao\Enum\SimpleChoiceEnum;

final class Gender extends SimpleChoiceEnum
{   
    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';
}

In addition, it'll provide default labels for each enumerated values based on a humanized version of their constant name (i.e: "MALE" becomes "Male". "SOME_VALUE" becomes "Some value"). In case you need more accurate labels, simply override the SimpleChoiceEnum::choices() implementation.

Flagged enums

Flagged enumerations are used for bitwise operations. Each value of the enumeration is a single bit flag and can be combined together into a valid bitmask in a single enum instance.

<?php

use Elao\Enum\FlaggedEnum;

final class Permissions extends FlaggedEnum
{
    public const EXECUTE = 1;
    public const WRITE = 2;
    public const READ = 4;

    // You can declare shortcuts for common bit flag combinations
    public const ALL = self::EXECUTE | self::WRITE | self::READ;

    public static function values(): array
    {
        return [
            // Only declare valid bit flags:
            static::EXECUTE,
            static::WRITE,
            static::READ,
        ];
    }

    public static function readables(): array
    {
        return [
            static::EXECUTE => 'Execute',
            static::WRITE => 'Write',
            static::READ => 'Read',

            // You can define readable values for specific bit flag combinations:
            static::WRITE | static::READ => 'Read & write',
            static::EXECUTE | static::READ => 'Read & execute',
            static::ALL => 'All permissions',
        ];
    }
}

Get instances using bitwise operations and manipulate them:

<?php
$permissions = Permissions::get(Permissions::EXECUTE | Permissions::WRITE | Permissions::READ);
$permissions = $permissions->withoutFlags(Permissions::EXECUTE); // Returns an instance without "execute" flag
$permissions->getValue(); // Returns 6 (int)
$permissions->getFlags(); // Returns [2, 4] (=> [Permissions::EXECUTE, Permissions::WRITE])

$permissions = $permissions->withoutFlags(Permissions::READ | Permissions::WRITE); // Returns an instance without "read" and "write" flags
$permissions->getValue(); // Returns Permissions::NONE (0). Note: NONE is defined in parent class, FlaggedEnum.
$permissions->getFlags(); // Returns an empty array

$permissions = Permissions::get(Permissions::NONE); // Returns an empty bitmask instance
$permissions = $permissions->withFlags(Permissions::READ | Permissions::EXECUTE); // Returns an instance with "read" and "execute" permissions
$permissions->hasFlag(Permissions::READ); // True
$permissions->hasFlag(Permissions::READ | Permissions::EXECUTE); // True
$permissions->hasFlag(Permissions::WRITE); // False

Compare

Enumeration values are singletons (exact term in this case actually is multiton): it means you'll always get the exact same instance for a given value. Thus, in order to compare two instances, you can simply use the strict comparison operator in order to check references:

<?php
Gender::get(Gender::MALE) === Gender::get(Gender::FEMALE); // False
Gender::get(Gender::MALE) === Gender::get(Gender::MALE); // True
Permissions::get(Permissions::ALL) === Permissions::get(
    Permissions::READ | Permissions::WRITE | Permissions::EXECUTE
); // True

You can also override the EnumInterface::equals(EnumInterface $enumToCompare) in order to implement your own logic to determine if two instances should be considered the same.
The default implementation compares both enum type (the class) and value.

<?php
Gender::get(Gender::MALE)->equals(Gender::get(Gender::FEMALE)); // False
Gender::get(Gender::MALE)->equals(Gender::get(Gender::MALE)); // True

Lastly, you can simply compare an instance with a value by using the EnumInterface::is($value):

<?php
Gender::get(Gender::MALE)->is(Gender::FEMALE); // False
Gender::get(Gender::MALE)->is(Gender::MALE); // True

Shortcuts

Inspired from myclabs/php-enum, you can use shortcuts to instantiate your enumerations, thanks to PHP's __callStatic magic method:

<?php
Gender::MALE(); // Returns an instance of Gender with the MALE value

We recommend you to use this method, if and only if, you and your team use an IDE (e.g PhpStorm) able to interpret the @method tag in class definitions. Then, you can benefit from IDE completion by declaring the following:

<?php

/**
 * @method static Gender UNKNOWN()
 * @method static Gender MALE()
 * @method static Gender FEMALE()
 */
final class Gender extends ReadableEnum
{
    public const UNKNOWN = 'unknown';
    public const MALE = 'male';
    public const FEMALE = 'female';
    
    // ...
}

Otherwise, simply implement the static methods yourself.

Integrations

Doctrine

You can store the raw value of an enumeration in the database, but still manipulate it as an object from your entities by creating a custom DBAL type, from scratch.

However, this library can help you by providing abstract classes for both string and integer based enumerations.

In a Symfony app

This configuration is equivalent to the following sections explaining how to create a custom Doctrine DBAL type for your enums.

elao_enum:
    doctrine:
        types:
            gender: App\Enum\GenderEnum # Defaults to `{ class: App\Enum\GenderEnum, type: string }` for string based enum (translates to VARCHAR)
            another: { class: App\Enum\AnotherEnum, type: enum } # string based enum with SQL ENUM column definition
            permissions: { class: App\Enum\Permissions, type: int } # values are stored as integers. Default for flagged enums.
            activity_types: { class: App\Enum\ActivityType, type: json_collection } # values are stored as a json array of enum values.
            roles: { class: App\Enum\Role, type: csv_collection } # values are stored as a csv (Doctrine simple_array) of enum values.

It'll actually generate & register the types classes for you, saving you from writing this boilerplate code.

You can also default to SQL ENUM column definitions by default for all types by using:

elao_enum:
    doctrine:
        enum_sql_declaration: true

Beware that your database platform must support it. Also, the Doctrine diff tool is unable to detect new or removed values, so you'll have to handle this in a migration yourself.

Create the DBAL type

First, create your DBAL type by extending either AbstractEnumType (string based enum), AbstractEnumSQLDeclarationType (if you want to use SQL ENUM column definition for string enums) or AbstractIntegerEnumType (integer based enum, for flagged enums for instance):

<?php

use Elao\Enum\Bridge\Doctrine\DBAL\Types\AbstractEnumType;

final class GenderEnumType extends AbstractEnumType
{
    public const NAME = 'gender';

    protected function getEnumClass(): string
    {
        return Gender::class;
    }

    public function getName(): string
    {
        return static::NAME;
    }
}

Register the DBAL type

Then, you'll simply need to register your DBAL type:

Manually

<?php
// in bootstrapping code
// ...
use Doctrine\DBAL\Types\Type;
Type::addType(GenderEnumType::NAME, GenderEnumType::class);

To convert the underlying database type of your new "gender" type directly into an instance of Gender when performing schema operations, the type has to be registered with the database platform as well:

<?php
$conn = $em->getConnection();
$conn->getDatabasePlatform()->registerDoctrineTypeMapping(GenderEnumType::NAME, GenderEnumType::class);

Using the Doctrine Bundle with Symfony

refs:

# config/packages/doctrine.yaml
doctrine:
    dbal:
        types:
            gender: App\Doctrine\DBAL\Types\GenderEnumType

Mapping

When registering the custom types in the configuration, you specify a unique name for the mapping type and map it to the corresponding fully qualified class name. Now the new type can be used when mapping columns:

<?php
class User
{
    /** @Column(type="gender") */
    private Gender $gender;
}

Default value on null

Two methods allow to set a default value if null is retrieved from the database, or before persisting a value:

<?php

abstract class AbstractEnumType extends Type
{
    // ...

    /**
     * What should be returned on null value from the database.
     *
     * @return mixed
     */
    protected function onNullFromDatabase()
    {
        return null;
    }

    /**
     * What should be returned on null value from PHP.
     *
     * @return mixed
     */
    protected function onNullFromPhp()
    {
        return null;
    }
}

Override those methods in order to satisfy your needs.

Symfony HttpKernel component

Available for Symfony 4.4+

An argument value resolver allows to seamlessly transform an HTTP request parameter (from route/attributes, query string or post parameters, in this order) into an enum instance by type-hinting the targeted enum in controller action.

The Elao\Enum\Bridge\Symfony\HttpKernel\Controller\ArgumentResolver\EnumValueResolver is automatically registered by the Symfony Bundle.

Symfony Serializer component

Available for Symfony 4.4+

The Elao\Enum\Bridge\Symfony\Serializer\Normalizer\EnumNormalizer is automatically registered by the Symfony Bundle and allows to normalize/denormalize any enumeration to/from its value.

Symfony Form component

Available for Symfony 4.4+

Simple enums

Simply use the EnumType:

<?php

use Elao\Enum\Bridge\Symfony\Form\Type\EnumType;
use MyApp\Enum\Gender;

// ...

$builder->add('gender', EnumType::class, [
    'enum_class' => Gender::class,
]);

// ...

$form->submit($data);
$form->get('gender')->getData(); // Will return a `Gender` instance (or null)

Only the enum_class option is required.

You can use any ChoiceType option as usual (for instance the multiple option).

The field data will be an instance of your enum. If you only want to map values, you can use the as_value option:

<?php

use Elao\Enum\Bridge\Symfony\Form\Type\EnumType;
use MyApp\Enum\Gender;

// ...

$builder->add('gender', EnumType::class, [
    'enum_class' => Gender::class,
    'as_value' => true,
]);

// ...

$form->submit($data);
$form->get('gender')->getData(); // Will return a string value defined in the `Gender` enum (or null)

You can restrict the list of proposed enumerations by overriding the choices option:

<?php

use Elao\Enum\Bridge\Symfony\Form\Type\EnumType;
use MyApp\Enum\Gender;

// ...

$builder->add('gender', EnumType::class, [
    'enum_class' => Gender::class,
    'choices' => [
        Gender::get(Gender::MALE), 
        Gender::get(Gender::FEMALE),
    ],
]);

// or:

$builder->add('gender', EnumType::class, [
    'enum_class' => Gender::class,
    'as_value' => true,
    'choices' => [
        Gender::readableFor(Gender::MALE) => Gender::MALE,
        Gender::readableFor(Gender::FEMALE) => Gender::FEMALE,
    ],
]);

Usually, when expecting data to be enum instances, choices must be provided as enum instances too, while when expecting enumerated values, choices are expected to be raw enumerated values.

The choices_as_enum_values allows to act differently:

  • if true, the EnumType will expect choices to be raw values.
  • if false, the EnumType will expect choices to be enum instances.

By default, this option is set to the same value as as_value.

Flagged enums

Simply use the FlaggedEnumType (which extends EnumType):

<?php

use Elao\Enum\Bridge\Symfony\Form\Type\FlaggedEnumType;
use MyApp\Enum\Permissions;

// ...

$builder->add('permissions', FlaggedEnumType::class, [
    'enum_class' => Permissions::class,
]);

// ...

$form->submit($data);
$form->get('permissions')->getData(); // Will return a single `Permissions` instance composed of selected bit flags

Same options are available, but on the contrary of the EnumType, the multiple option is always true and cannot be set to false (You'll always get a single enum instance though).

Symfony Validator component

Available for Symfony 4.4+

The library provides a Elao\Enum\Bridge\Symfony\Validator\Constraint\Enum constraint which makes use of Symfony's built-in Choice constraint and validator internally.

To use the constraint, simply provide the enum class:

# config/validator/validation.yaml
App\Entity\User:
    properties:
        gender:
            - Elao\Enum\Bridge\Symfony\Validator\Constraint\Enum: MyApp\Enum\Gender

If the property value is not an enum instance, set the asValue option to true in order to simply validate the enum value:

# config/validator/validation.yaml
App\Entity\User:
    properties:
        gender:
            - Elao\Enum\Bridge\Symfony\Validator\Constraint\Enum:
                class: MyApp\Enum\Gender
                asValue: true

You can restrict the available choices by setting the allowed values in the choices option:

# config/validator/validation.yaml
App\Entity\User:
    properties:
        gender:
            - Elao\Enum\Bridge\Symfony\Validator\Constraint\Enum:
                class: MyApp\Enum\Gender
                choices: 
                    - female
                    - !php/const MyApp\Enum\Gender::MALE

The choice option only accepts enum values and normalize it internally to enum instances if asValue is false.

You can also use a callback:

# config/validator/validation.yaml
App\Entity\User:
    properties:
        gender:
            - Elao\Enum\Bridge\Symfony\Validator\Constraint\Enum:
                class: MyApp\Enum\Gender
                callback: 'allowedValues'

Where allowedValues is a static method of MyApp\Enum\Gender, returning allowed values or instances.

Any other Choice option (as multiple, min, ...) is available with the Enum constraint.

Symfony VarDumper component

Available for Symfony 4.4+

By requiring this package and if symfony/var-dumper is installed, an EnumCaster is registered automatically to enhance enum instances dump output.

For instance, here's what it'll look like when dumping a flagged enum instance:

<?php

use Elao\Enum\Tests\Fixtures\Enum\Permissions;

dump(Permissions::get(Permissions::ALL));
HTML output CLI output
var-dumper-integration-cli var-dumper-integration-cli

Faker

The PhpEnums library provides an Elao\Enum\Bridge\Faker\Provider\EnumProvider to generate fixtures.

Its constructor receives a mapping between class aliases and your Enum classes' FQCN as first parameter:

<?php

use Elao\Enum\Bridge\Faker\Provider\EnumProvider;

$provider = new EnumProvider([
    'Civility' => Namespace\To\MyCivilityEnum::class,
    'Gender' => Namespace\To\MyGenderEnum::class,
]);

The provider exposes two public methods:

  • EnumProvider::enum(string $enumValueShortcut): EnumInterface in order to generate a deterministic enum instance
  • EnumProvider::randomEnum(string $enumClassOrAlias): EnumInterface in order to generate a random enum instance
  • EnumProvider::randomEnums(string $enumClassOrAlias, int $count, bool $variable = true, int $min = 0): array in order to generate an array of random (unique) enum instances

Usage with Alice

If you're using the nelmio/alice package and the bundle it provides in order to generate fixtures, you can register the Faker provider by using the nelmio_alice.faker.generator:

# config/services.yaml
services:
    Elao\Enum\Bridge\Faker\Provider\EnumProvider:
        arguments:
            - Civility: Namespace\To\MyCivilityEnum
              Gender: Namespace\To\MyGenderEnum
        tags: ['nelmio_alice.faker.provider']

The following example shows how to use the provider within a Yaml fixture file:

MyEntity:
    entity1:
        civility: <enum(Civility::MISTER)>
        # You can use enums outside of map if you specify full path to Enum class:
        gender: <enum("App\Model\Enum\Gender::MALE">
        # You can use the pipe character in order to combine flagged enums:
        permissions: <enum(Permissions::READ|WRITE>
    entity2:
        civility: <randomEnum(Civility)>
        gender: <randomEnum("App\Model\Enum\Gender")>
        permissions: <randomEnum(Permissions)>

📝 MISTER in <enum(Civility::MISTER)> refers to a constant defined in the Civility enum class, not to a constant's value ('mister' string for instance).

API Platform

OpenApi / Swagger

The library provides an Elao\Enum\Bridge\ApiPlatform\Core\JsonSchema\Type\ElaoEnumType to generate a OpenApi (formally Swagger) documentation based on your enums. This decorator is automatically wired for you when using the Symfony bundle.

JavaScript

This library allows to generate JS code from your PHP enums using a command:

bin/elao-enum-dump-js --lib-path "./assets/js/lib/enum.js" --base-dir="./assets/js/modules" \
    "App\Auth\Enum\Permissions:auth/Permissions.js" \
    "App\Common\Enum\Gender:common/Gender.js"

This command generates:

  • library sources at path assets/js/lib/enums.js containing the base JS classes
  • enums in a base /assets/js/modules dir:
    • Permissions in /assets/js/modules/auth/Permissions.js
    • Gender in /assets/js/modules/common/Gender.js

Simple enums, readables & flagged enums are supported.

Note that this is not meant to be used as part of an automatic process updating your code. There is no BC promise guaranteed on the generated code. Once generated, the code belongs to you.

In a Symfony app

You can configure the library path, base dir and enum paths in the bundle configuration:

elao_enum:
    elao_enum:
        js:
            base_dir: '%kernel.project_dir%/assets/js/modules'
            lib_path: '%kernel.project_dir%/assets/js/lib/enum.js'
            paths:
                App\Common\Enum\SimpleEnum: 'common/SimpleEnum.js'
                App\Common\Enum\Gender: 'common/Gender.js'
                App\Auth\Enum\Permissions: 'auth/Permissions.js'

Then, use the CLI command to generate the JS files:

bin/console elao:enum:dump-js [--lib-path] [--base-dir] [<enum:path>...]

Twig

The EnumExtension exposes static methods of the enum classes through the following Twig functions:

  • enum_get($class, $value)
  • enum_values($class)
  • enum_accepts($class, $value)
  • enum_instances($class)
  • enum_readables($class)
  • enum_readable_for($class, $value)

API

Simple enum

Method Static Returns Description
get($value) Yes static Returns the instance of the enum type for given value.
values() Yes int[]|string[] Should return any possible value for the enumeration.
accepts($value) Yes bool True if the value is acceptable for this enumeration.
instances() Yes static[] Instantiates and returns an array containing every enumeration instance for possible values.
getValue() No int|string Returns the enumeration instance value.
equals(EnumInterface $enum) No bool Determines whether two enumerations instances should be considered the same.
is($value) No bool Determines if the enumeration instance value is equal to the given value.

Readable enum

Method Static Returns Description
readables() Yes string[] Should return an array of the human representations indexed by possible values.
readableFor($value) Yes string Get the human representation for given enumeration value.
getReadable() No string Get the human representation for the current instance.
__toString() No string Allows to convert the instance to the human representation of the current value by casting it to a string.

Flagged enum

Method Static Returns Description
accepts($value) Yes bool Same as before, but accepts bit flags and bitmasks.
readableForNone() Yes string Override this method to replace the default human representation of the "no flag" value.
readableFor($value, string $separator = '; ') Yes string Same as before, but allows to specify a delimiter between single bit flags (if no human readable representation is found for the combination).
getReadable(string $separator = '; ') No string Same as before, but with a delimiter option (see above).
getFlags() No int[] Returns an array of bit flags set in the current enumeration instance.
hasFlag(int $bitFlag) No bool True if the current instance has the given bit flag(s).
withFlags(int $flags) No static Computes a new value with given flags, and returns the corresponding instance.
withoutFlags(int $flags) No static Computes a new value without given flags, and returns the corresponding instance.
Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].