Skip to content

Instantly share code, notes, and snippets.

@drolean
Forked from jhoff/Enums.php
Created October 23, 2017 12:33
Show Gist options
  • Save drolean/fe5aa8c84d65bf9aa5e3e7e4b4c7bf4a to your computer and use it in GitHub Desktop.
Save drolean/fe5aa8c84d65bf9aa5e3e7e4b4c7bf4a to your computer and use it in GitHub Desktop.

Revisions

  1. Jordan Hoff revised this gist Nov 7, 2016. 1 changed file with 8 additions and 5 deletions.
    13 changes: 8 additions & 5 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -5,7 +5,10 @@ The `Enum` trait is a really useful way to allow you to pre-define all of the va
    ### Add the `Enum` trait to your model

    ```
    namespace App;
    use App\Traits\Enums;
    use Illuminate\Database\Eloquent\Model;
    class Post extends Model
    {
    @@ -16,7 +19,7 @@ class Post extends Model

    ### Sample Usage

    Model `Post` has an enumerated field called `status` that we want to enforce specific values for.
    Model `App\Post` has an enumerated field called `status` that we want to enforce specific values for.

    ```
    class Post extends Model
    @@ -46,26 +49,26 @@ class Post extends Model
    Once you've defined this `$enum` property on the model, any time that field is set on any instance, a validation process will run to enforce that the value is being set properly:

    ```
    $post = new Post;
    $post = new App\Post;
    $post->status = 'Something Invalid';
    // Throws an InvalidEnumException
    ```

    ```
    $post = Post::first();
    $post = App\Post::first();
    $post->status = 'Draft';
    // Sets the value to Draft as expected
    ```

    ```
    // Key values will always work to set the value as well,
    // so using the non-associative array example, this will set status to 'Draft'
    $post = Post::create([
    $post = App\Post::create([
    'status' => 0
    ]);
    // Using the associative array example, this will set status to 'Published'
    $post = Post::create([
    $post = App\Post::create([
    'status' => 'pu'
    ]);
    ```
  2. Jordan Hoff revised this gist Nov 7, 2016. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -73,13 +73,13 @@ $post = Post::create([
    Enumerations work really well in blade files too. Simply use the `getEnum` static helper:

    ```
    @foreach( Post::getEnum('status') as $key => $value)
    @foreach( App\Post::getEnum('status') as $key => $value)
    {{ $key }}: {{ $value }}
    @endforeach
    ```

    Or use them with the LaravelCollective form builder:

    ```
    {{ Form::select('status', Post::getEnum('status')) }}
    {{ Form::select('status', App\Post::getEnum('status')) }}
    ```
  3. Jordan Hoff revised this gist Nov 7, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,4 +1,4 @@
    ## Laravel Model `Enum` Trait
    ## Laravel Model Enumeration Trait

    The `Enum` trait is a really useful way to allow you to pre-define all of the valid values for a given field on a model and enforce that their values are set appropriately. This basically allows you to treat a field as a menu without the database overhead of dealing with true enum fields or lookup tables.

  4. Jordan Hoff revised this gist Nov 7, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -82,4 +82,4 @@ Or use them with the LaravelCollective form builder:

    ```
    {{ Form::select('status', Post::getEnum('status')) }}
    ```
    ```
  5. Jordan Hoff revised this gist Oct 26, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion README.md
    Original file line number Diff line number Diff line change
    @@ -1,6 +1,6 @@
    ## Laravel Model `Enum` Trait

    The `Enum` trait is a really useful way to allow you to pre-define all of the valid values for a given field on a model and enforce that their values are set appropriately. This basically allows you to treat a field as a menu.
    The `Enum` trait is a really useful way to allow you to pre-define all of the valid values for a given field on a model and enforce that their values are set appropriately. This basically allows you to treat a field as a menu without the database overhead of dealing with true enum fields or lookup tables.

    ### Add the `Enum` trait to your model

  6. Jordan Hoff created this gist Oct 26, 2016.
    125 changes: 125 additions & 0 deletions Enums.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,125 @@
    <?php

    namespace App\Traits;

    use Illuminate\Support\Str;
    use App\Exceptions\InvalidEnumException;

    trait Enums
    {
    /**
    * Enum property getter
    *
    * @param string $field
    * @return mixed|false
    */
    public static function getEnum(string $field)
    {
    $instance = new static;

    if ($instance->hasEnumProperty($field)) {
    $property = $instance->getEnumProperty($field);

    return $instance->$property;
    }

    return false;
    }

    /**
    * Check for the presence of a property that starts
    * with enum for the provided attribute
    *
    * @param string $field
    * @param mixed $value
    * @return $this
    * @throws InvalidEnumException
    */
    public function setAttribute($field, $value)
    {
    if ($this->hasEnumProperty($field)) {
    if (!$this->isValidEnum($field, $value)) {
    throw new InvalidEnumException("Invalid value for " . static::class . "::$field ($value)");
    }

    if ($this->isKeyedEnum($field, $value)) {
    $value = $this->getKeyedEnum($field, $value);
    }
    }

    return parent::setAttribute($field, $value);
    }

    /**
    * Gets the expected enum property
    *
    * @param string $field
    * @return string
    */
    protected function getEnumProperty(string $field)
    {
    return 'enum' . Str::plural(Str::studly($field));
    }

    /**
    * Gets the enum value by key
    *
    * @param string $field
    * @param mixed $key
    * @return mixed
    */
    protected function getKeyedEnum(string $field, $key)
    {
    return static::getEnum($field)[$key];
    }

    /**
    * Is an enum property defined for the provided field
    *
    * @param string $field
    * @return boolean
    */
    protected function hasEnumProperty(string $field)
    {
    $property = $this->getEnumProperty($field);

    return isset($this->$property) && is_array($this->$property);
    }

    /**
    * Is the provided value a key in the enum
    *
    * @param string $field
    * @param mixed $key
    * @return bool
    */
    protected function isKeyedEnum(string $field, $key)
    {
    return in_array($key, array_keys(static::getEnum($field)), true);
    }

    /**
    * Is the value a valid enum in any way
    *
    * @param string $field
    * @param mixed $value
    * @return bool
    */
    protected function isValidEnum(string $field, $value)
    {
    return $this->isValueEnum($field, $value) ||
    $this->isKeyedEnum($field, $value);
    }

    /**
    * Is the provided value in the enum
    *
    * @param string $field
    * @param mixed $value
    * @return bool
    */
    protected function isValueEnum(string $field, $value)
    {
    return in_array($value, static::getEnum($field));
    }
    }
    10 changes: 10 additions & 0 deletions InvalidEnumException.php
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,10 @@
    <?php

    namespace App\Exceptions;

    use Exception;

    class InvalidEnumException extends Exception
    {
    //
    }
    85 changes: 85 additions & 0 deletions README.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,85 @@
    ## Laravel Model `Enum` Trait

    The `Enum` trait is a really useful way to allow you to pre-define all of the valid values for a given field on a model and enforce that their values are set appropriately. This basically allows you to treat a field as a menu.

    ### Add the `Enum` trait to your model

    ```
    use App\Traits\Enums;
    class Post extends Model
    {
    use Enums;
    ...
    }
    ```

    ### Sample Usage

    Model `Post` has an enumerated field called `status` that we want to enforce specific values for.

    ```
    class Post extends Model
    {
    use Enums;
    // Define all of the valid options in an array as a protected property that
    // starts with 'enum' followed by the plural studly cased field name
    protected $enumStatuses = [
    'Draft',
    'Scheduled',
    'Published',
    'Archived'
    ];
    // Alternately, if you use an associative array, the keys can be used
    // to set the value as well. The full string will still be stored in the database.
    /* protected $enumStatuses = [
    'dr' => 'Draft',
    'sc' => 'Scheduled',
    'pu' => 'Published',
    'ar' => 'Archived'
    ]; */
    ...
    ```

    Once you've defined this `$enum` property on the model, any time that field is set on any instance, a validation process will run to enforce that the value is being set properly:

    ```
    $post = new Post;
    $post->status = 'Something Invalid';
    // Throws an InvalidEnumException
    ```

    ```
    $post = Post::first();
    $post->status = 'Draft';
    // Sets the value to Draft as expected
    ```

    ```
    // Key values will always work to set the value as well,
    // so using the non-associative array example, this will set status to 'Draft'
    $post = Post::create([
    'status' => 0
    ]);
    // Using the associative array example, this will set status to 'Published'
    $post = Post::create([
    'status' => 'pu'
    ]);
    ```

    Enumerations work really well in blade files too. Simply use the `getEnum` static helper:

    ```
    @foreach( Post::getEnum('status') as $key => $value)
    {{ $key }}: {{ $value }}
    @endforeach
    ```

    Or use them with the LaravelCollective form builder:

    ```
    {{ Form::select('status', Post::getEnum('status')) }}
    ```