henzeb/enumhancer

View on GitHub
docs/mappers.md

Summary

Maintainability
Test Coverage
# Mappers

This will allow you to map strings to existing enums. This is useful when you
for example are building against multiple third party API's and you need to
translate the enums between one and other.

Note: `Mappers` is the only one that you cannot use together with
`Getters`, `Extractor` and `Reporters`. This is simply due to the fact that it is
implementing the methods for those by itself. Under the hood it's using their
functionality, so the methods will work just the same.

## Usage

### simple constant definition

Just like with [Defaults](defaults.md), constants can be used to map a reference
to an existing enum key. When such a constant exists, Enumhancer treats it like any
other case.

````php
enum Suit
{
    use Henzeb\Enumhancer\Concerns\Mappers;

    case Hearts;
    case Clubs;
    case Spades;
    case Diamonds;

    const AceOfClubs = Suit::Clubs;
}

Suit::get('AceOfClubs'); //returns Suit::Clubs

````

Note: constants containing a reference to existing cases can also be set to `private`
to prevent direct reference.

### constant definitions

You can also add a constant definition with an array inside. The name
should be starting with `map`, either lower or uppercase.

````php
enum Suit
{
    use Henzeb\Enumhancer\Concerns\Mappers;

    private const MAP_SUIT = [
        'AceOfSpades' => Suit::Spades
    ];

    case Hearts;
    case Clubs;
    case Spades;
    case Diamonds;
}
Suit::get('AceOfSpades'); //returns Suit::Spades
````

You can also have multiple `mappers` specified that way. Just add another constant.

### The Mapper object

When you plan to use a different mapper for different situations, like languages,
You can create an object that extends `Henzeb\Enumhancer\Contracts\Mapper`.

````php
class SuitMapper extends Henzeb\Enumhancer\Contracts\Mapper
{
    protected function mappable(): array
    {
        return [
            'AceOfHearts' => 'hearts',
            'AceOfClubs' => 'Clubs',
            'AceOfSpades' => 2,
            'AceOfDiamonds' => Suit::Diamonds
        ];
    }
}
````

Just like cases, keys and values don't have to be in the correct case.

#### Using constants

Just like arrays, when a constant has a string that points to an actual
`Mapper`, Enumhancer will transform it into a Mapper object and use this.

````php
enum Suit
{
    use Henzeb\Enumhancer\Concerns\Mappers;

    private const MAP_SUIT = SuitMapper::class;

    case Hearts;
    case Clubs;
    case Spades;
    case Diamonds;
}

Suit::get('AceOfDiamonds'); //returns Suit::Diamonds
````

#### Using a static method

In some cases you might want to apply the mapper through a method.

````php
enum Suit
{
    use Henzeb\Enumhancer\Concerns\Mappers;

    case Hearts;
    case Clubs;
    case Spades;
    case Diamonds;

    protected static function mapper(): Henzeb\Enumhancer\Contracts\Mapper|array|string|null
    {
        return SuitMapper::class;
    }
}

Suit::get('AceOfHearts'); // returns Suit::Hearts
````

#### add as parameter

If you wish, you can add as many mappers as you like to any of the
[Getters](getters.md) methods.

````php
Suit::get('AceOfHearts', SuitMapper::class, SuitMapperFrench::class);
Suit::get('AceOfHearts', SuitMapper::getNewInstance());
Suit::tryGet('AceOfHearts', ['AceOfClubs'=>'AceOfHearts']);
````

#### using Configure

See [Configure](configure.md#configuremapper)

#### Combining the different ways

It's possible to combine the different methods. Mapping values is done waterfall.
This means a mapper can map to a value that does not necessarily exist in the `enum`
object, so another mapper can map that value to the final case.

````php
enum Suit
{
    use Henzeb\Enumhancer\Concerns\Mappers;

    private const MAP_SUIT = [
        'AceOfHearts' => 'AceOfClubs'
    ];

    private const MAP_FINAL = [
        'AceOfClubs' => Suit::Spades
    ];

    case Hearts;
    case Clubs;
    case Spades;
    case Diamonds;
}

Suit::get('AceOfHearts'); //returns Suit::Spades
````

The order of precedence is as follows:

- Any mappers passed by argument in order of appearance
- Mapper returned by [static method](#using-a-static-method)
- Mappers set by [Configure](configure.md#configuremapper)
- Mappers (array or class name) defined in constants in order
 of appearance

#### Shared mappers

The mapper object allows you to share one single object for multiple
enums. For that to work, you have to return a multidimensional array
that has a key pointing at your enum containing an array of what you
want to map for this particular enum.

````php
class SuitMapper extends Henzeb\Enumhancer\Contracts\Mapper
{
    protected function mappable(): array
    {
        return [
            Suit::class => [
                'AceOfHearts' => 'hearts',
                'AceOfClubs' => 1,
                'AceOfSpades' => 'Spades',
            ],
            'AceOfDiamonds' => Suit::Diamonds
        ];
    }
}
````

#### Defined

If, for some reason, you want to know if a value is defined,
you can check that with this method.

````php
$suitMapper->defined('AceOfDiamonds'); // returns true
$suitMapper->defined('AceOfDiamonds', Suit::class); // returns true

$suitMapper->defined('AceOfHearts'); // returns false
$suitMapper->defined('AceOfHearts', Suit::class); // returns true

SuitMapper::defined('AceOfDiamonds'); // returns true
SuitMapper::defined('AceOfDiamonds', Suit::class); // returns true

SuitMapper::defined('AceOfHearts'); // returns false
SuitMapper::defined('AceOfHearts', Suit::class); // returns true
````

#### Keys

The `keys` method shows you a list of defined keys.

In case of a shared mapper, without the enum class name, `keys`
will only return global map keys.

````php
$suitMapper->keys();
$suitMapper->keys(Suit::class);
SuitMapper::keys();
SuitMapper::keys(Suit::class);
````

#### Flip

In some cases, you might want to flip your map. Instead of
creating a second mapper, you can just call flip on your existing
mapper.

In case of a shared mapper, without the enum class name, only
global map keys will be flipped and used for mapping.

````php
$suitMapper->flip();
$suitMapper->flip(Suit::class);
SuitMapper::flip();
SuitMapper::flip(Suit::class);
````

Just like with `MAP`, you can add constants starting with
`MAP_FLIP` (again, uppercased or lowercased) to point at your mapper.

````php
enum Suit
{
    use Henzeb\Enumhancer\Concerns\Mappers;

    private const MAP_FLIP_SUIT = SuitMapper::class;

    case Hearts;
    case Clubs;
    case Spades;
    case Diamonds;
}
````