Skip to content

Latest commit

 

History

History
269 lines (201 loc) · 6.35 KB

mappers.md

File metadata and controls

269 lines (201 loc) · 6.35 KB

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, 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.

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.

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.

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.

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.

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 methods.

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

using Configure

See Configure

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.

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
  • Mappers set by Configure
  • 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.

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.

$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.

$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.

$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.

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

    private const MAP_FLIP_SUIT = SuitMapper::class;

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