Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Enumhancer Laravel Package

henzeb/enumhancer

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require henzeb/enumhancer
    

    No service provider or facade needed—just autoload and use.

  2. First Use Case: Basic Enum Definition Define a simple enum in a file (e.g., app/Enums/UserRole.php):

    use HenzeB\Enumhancer\Enum;
    
    enum UserRole: string
    {
        use Enum;
    
        case ADMIN = 'admin';
        case EDITOR = 'editor';
        case VIEWER = 'viewer';
    }
    
  3. Key Features to Try Immediately

    • Case-insensitive access:
      UserRole::from('AdMiN'); // Returns UserRole::ADMIN
      
    • Type-agnostic operations:
      UserRole::ADMIN->value; // 'admin' (string)
      UserRole::ADMIN->toString(); // 'ADMIN'
      
    • Collection methods:
      UserRole::all()->pluck('value'); // ['admin', 'editor', 'viewer']
      
  4. Where to Look First

    • README for core features.
    • API Docs for method reference.
    • tests/ directory for usage examples (e.g., EnumTest.php).

Implementation Patterns

Common Workflows

1. Database Integration (Laravel)

Use fromDatabase() for case-insensitive DB value handling:

$role = UserRole::fromDatabase('ADMIN'); // Works for 'admin', 'Admin', etc.

Model Casting:

use HenzeB\Enumhancer\Casts\EnumCast;

protected $casts = [
    'role' => EnumCast::class,
];

2. Validation

Leverage isValid() for input validation:

if (UserRole::isValid('editor')) {
    // Proceed
}

Form Request Example:

public function rules()
{
    return [
        'role' => ['required', Rule::in(UserRole::all()->pluck('value'))],
    ];
}

3. API Responses

Use toArray() or jsonSerialize() for consistent serialization:

return response()->json([
    'role' => UserRole::ADMIN->toArray(), // ['value' => 'admin', 'name' => 'ADMIN']
]);

4. Dynamic Enums

Extend Enum for reusable traits:

trait HasDescription {
    public function description(): string {
        return match($this) {
            self::ADMIN => 'Full access',
            self::EDITOR => 'Limited access',
            default => 'Read-only',
        };
    }
}

Apply to enum:

enum UserRole: string {
    use Enum, HasDescription;
    // ...
}

5. Localization

Use getLabel() with a custom resolver:

UserRole::setLabelResolver(function (string $value) {
    return __("roles.{$value}");
});

Integration Tips

Laravel-Specific

  • Pivot Tables: Cast enum values in pivot models:
    protected $casts = [
        'permission' => EnumCast::class,
    ];
    
  • Query Scopes: Filter by enum values:
    public function scopeWithRole(Builder $query, UserRole $role)
    {
        return $query->where('role', $role->value);
    }
    

Testing

  • Assertions: Use assertIs() with Enumhancer's assertions:
    $this->assertIs(UserRole::class, UserRole::from('admin'));
    
  • Mocking: Override from() for tests:
    UserRole::shouldReceive('from')->andReturn(UserRole::VIEWER);
    

Performance

  • Cache Enum Instances: For frequently used enums, cache the all() result:
    $roles = Cache::remember('user_roles', now()->addHour(), function () {
        return UserRole::all();
    });
    

Gotchas and Tips

Pitfalls

  1. Case Sensitivity in Backed Enums

    • Even though Enumhancer is case-agnostic, backed enums (e.g., enum UserRole: string) will still enforce strict type matching for raw values.
    • Fix: Use from() or fromDatabase() instead of direct casting:
      // ❌ Avoid:
      UserRole::from('ADMIN')->value; // May fail if DB returns 'admin'
      
      // ✅ Use:
      UserRole::fromDatabase('admin'); // Works
      
  2. Overriding Default Methods

    • If you extend Enum with custom traits/methods, ensure they don’t conflict with Enumhancer's magic methods (e.g., __toString()).
    • Tip: Prefix custom methods with custom() or use namespaces:
      public function customDescription(): string { ... }
      
  3. Serialization Quirks

    • jsonSerialize() may not work as expected if the enum implements custom serialization logic.
    • Fix: Explicitly call toArray() or toJson():
      json_encode(UserRole::ADMIN->toArray());
      
  4. AGPL License Implications

    • The AGPL-3.0 license requires open-sourcing modified versions of Enumhancer or applications using it if they interact with users over a network.
    • Tip: Review AGPL compliance if integrating into a closed-source project.

Debugging Tips

  1. Unknown Enum Values

    • If from() returns null, check for typos or whitespace:
      UserRole::from('  admin  ')->trimmed(); // Helper to trim values
      
  2. Method Not Found

    • Ensure the use Enum; trait is at the top of the enum class (before case definitions).
  3. Performance Bottlenecks

    • Avoid calling all() in loops. Cache results or use lazy evaluation:
      UserRole::all()->filter(fn ($role) => $role->value === 'admin');
      

Extension Points

  1. Custom Label Resolvers Override default label behavior globally:

    UserRole::setLabelResolver(function (UserRole $enum) {
        return "Role: {$enum->name} ({$enum->value})";
    });
    
  2. Adding Validation Rules Extend the enum with custom validation logic:

    enum UserRole: string {
        use Enum;
    
        public function isActive(): bool {
            return $this !== self::VIEWER;
        }
    }
    
  3. Database-Specific Adapters Create a custom adapter for non-standard DB value formats:

    UserRole::setDatabaseAdapter(function (string $value) {
        return strtoupper($value); // Force uppercase for DB
    });
    
  4. Event Dispatching Trigger events on enum operations (e.g., onFrom()):

    UserRole::onFrom(function (string $value, UserRole $enum) {
        event(new EnumUsed($enum, $value));
    });
    

Config Quirks

  1. Default Label Format

    • By default, labels use the enum name (e.g., ADMIN"ADMIN").
    • Override globally:
      UserRole::setLabelFormat('{name} ({value})');
      
  2. Strict Mode

    • Enable to throw exceptions on invalid from() calls:
      UserRole::setStrict(true);
      UserRole::from('invalid'); // Throws \InvalidArgumentException
      
  3. Backed Enum Handling

    • If using backed enums, ensure the value property matches the enum’s type (e.g., string, int). Mismatches may cause silent failures.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
iio/libmergepdf
redaxo/project
zatona-eg/zatona-eg-api
patrickbussmann/oauth2-apple
3brs/enterprise-security-bundle
ardenexal/fhir-models
ardenexal/fhir-validation
dpfx/laravel-livewire-wizards
dmstr/symfony-system-resources-bundle
dmstr/symfony-job-queue-bundle
dmstr/openapi-json-schema-bundle
dmstr/keycloak-security-bundle
dmstr/doctrine-audit-log-bundle
dmstr/api-platform-utils-bundle
dmstr/api-configuration-bundle
chrisdev/ux-components
crudly/encrypted
cuci/prototurk-sdk
gos/pubsub-router-bundle
cuci/prototurk-sdk-symfony