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

Typed Enum Laravel Package

laudis/typed-enum

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Steps

  1. Installation:

    composer require laudis/typed-enum
    

    Add to composer.json under require:

    "require": {
        "laudis/typed-enum": "^1.0"
    }
    
  2. First Enum Class: Create a final class extending TypedEnum in app/Enums/ (or your preferred namespace):

    namespace App\Enums;
    
    final class UserRole extends \TypedEnum
    {
        private const ADMIN = 'admin';
        private const EDITOR = 'editor';
        private const VIEWER = 'viewer';
    }
    
  3. First Usage:

    use App\Enums\UserRole;
    
    // Create an instance
    $role = UserRole::ADMIN();
    
    // Get the value
    $roleValue = $role->getValue(); // 'admin'
    
    // Strict comparison
    if ($role === UserRole::ADMIN()) {
        // Do something
    }
    
  4. IDE Integration: Add @method tags to your enum class for autocompletion:

    /**
     * @method static UserRole ADMIN()
     * @method static UserRole EDITOR()
     * @method static UserRole VIEWER()
     */
    final class UserRole extends \TypedEnum
    {
        // ...
    }
    

Implementation Patterns

Core Workflows

1. Defining Enums

  • Group Related Values: Use enums for domain-specific constants (e.g., OrderStatus, PaymentMethod).
  • Scalar Types: Support string, int, or float values.
    final class OrderStatus extends \TypedEnum
    {
        private const PENDING = 'pending';
        private const COMPLETED = 1;
        private const CANCELED = 2.0;
    }
    
  • Private Constants: Ensure safety by using private const (PHP 7.4+).

2. Type-Hinting in Laravel

  • Controllers/Requests:
    public function updateStatus(Request $request, OrderStatus $status)
    {
        // $status is guaranteed to be a valid OrderStatus enum
    }
    
  • Services/Repositories:
    public function findByStatus(OrderStatus $status): Collection
    {
        return Order::where('status', $status->value)->get();
    }
    

3. Database Integration

  • Model Casting:
    protected $casts = [
        'status' => OrderStatus::class,
    ];
    
  • Query Building:
    $pendingOrders = Order::where('status', OrderStatus::PENDING()->value)->get();
    
  • Migrations:
    $table->string('status')->comment('OrderStatus::PENDING, OrderStatus::COMPLETED, etc.');
    

4. API Responses

  • JSON Serialization:
    public function toArray(): array
    {
        return [
            'status' => $this->status->value,
            'name' => $this->status->name(),
        ];
    }
    
  • Validation:
    use Illuminate\Validation\Rule;
    
    $rules = [
        'status' => ['required', Rule::in(array_column(OrderStatus::cases(), 'value'))],
    ];
    

5. Resolving Values

  • Reverse Lookup:
    $statuses = OrderStatus::resolve('pending'); // Returns array of matching enums
    $firstMatch = $statuses[0] ?? null;
    
  • Dynamic Filtering:
    $activeRoles = UserRole::resolve('admin')->merge(UserRole::resolve('editor'));
    

6. Testing

  • Unit Tests:
    public function test_status_comparison()
    {
        $this->assertSame(OrderStatus::PENDING(), OrderStatus::resolve('pending')[0]);
    }
    
  • Pest Example:
    it('validates order status', function () {
        expect(OrderStatus::PENDING())->toBe(OrderStatus::resolve('pending')[0]);
    });
    

7. Psalm Integration

  • Type Annotations:
    /**
     * @extends \TypedEnum<string>
     */
    final class UserRole extends \TypedEnum
    {
        // ...
    }
    
  • Static Analysis: Psalm will catch invalid enum usage (e.g., UserRole::INVALID).

Advanced Patterns

1. Enum Collections

  • Iterate Over Cases:
    foreach (OrderStatus::cases() as $status) {
        // $status is an instance of OrderStatus
    }
    
  • Filter Cases:
    $completedStatuses = collect(OrderStatus::cases())
        ->filter(fn ($status) => $status->value === 'completed');
    

2. Enum in Config

  • Replace Magic Strings:
    // config/app.php
    'default_role' => UserRole::VIEWER()->value,
    
  • Dynamic Config:
    config(['app.roles' => array_column(UserRole::cases(), 'value')]);
    

3. Enum in Artisan Commands

  • Type-Hinted Arguments:
    protected $signature = 'order:update {status : OrderStatus}';
    
  • Enum-Based Logic:
    public function handle()
    {
        if ($this->argument('status') === OrderStatus::CANCELED()) {
            // Handle cancellation
        }
    }
    

4. Enum in Livewire

  • Reactive Properties:
    public $status = OrderStatus::PENDING();
    
    public function updatedStatus()
    {
        $this->validate(['status' => 'required|in:' . implode(',', OrderStatus::cases())]);
    }
    
  • Dropdown Options:
    public function mount()
    {
        $this->statusOptions = collect(OrderStatus::cases())
            ->pluck('value', 'value')
            ->toArray();
    }
    

5. Enum in Queues/Jobs

  • Type-Safe Job Parameters:
    public function handle(OrderStatus $status)
    {
        // $status is guaranteed to be valid
    }
    
  • Dispatching:
    UpdateOrderStatus::dispatch(OrderStatus::COMPLETED());
    

6. Enum in Policies

  • Authorization Logic:
    public function update(User $user, Order $order)
    {
        return $user->role === UserRole::ADMIN() ||
               $order->userId === $user->id;
    }
    

7. Enum in Events

  • Type-Safe Event Payloads:
    class OrderStatusUpdated implements ShouldBroadcast
    {
        public function __construct(public OrderStatus $status) {}
    }
    

8. Enum in Notifications

  • Dynamic Content:
    public function toMail(Order $order)
    {
        return (new MailMessage)
            ->line("Order status updated to: {$order->status->value}");
    }
    

9. Enum in Observers

  • Model Events:
    public function saved(Order $order)
    {
        if ($order->status === OrderStatus::COMPLETED()) {
            // Trigger completion logic
        }
    }
    

10. Enum in API Resources

  • Custom Serialization:
    public function toArray($request)
    {
        return [
            'status' => $this->resource->status->value,
            'status_name' => $this->resource->status->name(),
        ];
    }
    

Gotchas and Tips

Pitfalls

  1. Duplicate Values:

    • Issue: If two constants share the same value (e.g., const A = 1; const B = 1;), resolve() returns an array.
    • Fix: Design enums to have unique values or handle arrays in resolve():
      $matches = OrderStatus::resolve('pending');
      $status = $matches[0] ?? throw new \InvalidArgumentException('No matching status');
      
  2. Case Sensitivity:

    • Issue: String enums are case-sensitive ('Admin''admin').
    • Fix: Standardize naming conventions (e.g., snake_case or UPPER_CASE).
  3. Private Constants:

    • Issue: PHP < 7.4 may not support private const. Use protected const as a fallback.
    • Fix: Update PHP version or use:
      protected const ADMIN = 'admin';
      
  4. IDE Autocompletion:

    • Issue: Without @method tags, IDEs won’t
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity