marc-mabe / php-enum

Simple and fast implementation of enumerations with native PHP
BSD 3-Clause "New" or "Revised" License
464 stars 36 forks source link

Support arrays as enum values in phpDoc #96

Closed tdtm closed 5 years ago

tdtm commented 6 years ago

Constants can be arrays since PHP 5.6. Everything works so far if using arrays, but phpDoc & type checking fails.

EDIT: might have to add test cases for that as well.

eg if using:

class MyEnum extends \MabeEnum\Enum{
    const SOMEVAL = ['someprop' => 'someval', 'anotherprop' => 'anotherval'];
}

This causes warnings on:

MyEnum::get(MyEnum::SOMEVAL);

I can look at doing a PR for it.

prolic commented 6 years ago

I'm not sure if this is still an enum then.

marc-mabe commented 6 years ago

As arrays are supported as const values but all array keys/values have to be constant, too it is fine.

We even already document that it's working in our README:

// all scalar data types and arrays are supported as enumerator values const NIL = null; const BOOLEAN = true; const INT = 1234; const STR = 'string'; const FLOAT = 0.123; const ARR = ['this', 'is', ['an', 'array']];

again PR would be nice :)

tdtm commented 6 years ago

I haven't done Java in a long time, but if I remember right enums can have a number of properties - the use case for enums I have here comes from my (blurry) memory of this.

I can't post actual source but something more concrete and close to my case:

class CONTENTTYPE extends \MabeEnum\Enum {
    const ARTICLE = ['isIndexable' => true, 'isTranslatable' => true];
    const TAG     = ['isIndexable' => true, 'isTranslatable' => false];

    public function isTranslatable() { return $this->getValue()['isIndexable']; }
    public function isIndexable() { return $this->getValue()['isTranslatable']; }
}
marc-mabe commented 6 years ago

@tdtm Personally in your case I would write that differently:

class ContentType extends Enum {
    const ARTICLE = 'article';
    const TAG = 'tag';

    private static $translatable = [self::ARTICLE];
    private static $indexable = [self::ARTICLE, self::TAG];

    public function isTranslatable() { return in_array($this->value, self::$translatable, true); }
    public function isIndexable() { return in_array($this->value, self::$indexable, true); }
}
tdtm commented 6 years ago

@marc-mabe That would work for that specific example, though I don't find it as readable. By having those in an array as the constant value, you know its entire definition at a glance just by looking at ARTICLE. With your solution, you also have to look at $translatable and $indexable and actually find your constant in it - and it works for booleans only, not if the value is any other type.

Will do a PR :)

tdtm commented 6 years ago

An better example I have is where I'm replacing a big switch similar to this:

function icon($icon_type) {
    switch ($icon_type)
    {
        case 'cog':
            $label = 'settings';
            $url = '//exemple.com/assets/images/cog.svg';
            break;

        (...etc...)

    }

    return ['label' => $label, 'url' => $url];
}

then displaying with the label and url indexes, and passing the 'cog' string around.

Instead, I want:

class ICON extends \MabeEnum\Enum {
    const COG = ['label' => 'settings', 'url' => '//exemple.com/assets/images/cog.svg'];
    const GROUP = ['label' => 'group', 'url' => '//exemple.com/assets/images/group.svg'];

    public function getLabel() { return $this->getValue()['label']; }
    public function getUrl() { return $this->getValue()['url']; }
}

So when setting an icon, I can actually typehint "ICON" and pass that around, rather than a text string, and use the getters rather than array indexes.

I hope that's a slightly better example!

marc-mabe commented 5 years ago

implemented by 9ad4dda #106

tdtm commented 5 years ago

Thanks @marc-mabe, you rock. Sorry I never got around to follow-up with a PR.