weijukeji / laravel-enum-options
A Laravel package for handling enums with frontend-friendly options (labels, colors, icons) and multi-language support
Installs: 0
Dependents: 0
Suggesters: 0
Security: 0
Stars: 0
Watchers: 0
Forks: 0
Open Issues: 0
pkg:composer/weijukeji/laravel-enum-options
Requires
- php: ^8.1
- illuminate/console: ^10.0|^11.0|^12.0
- illuminate/support: ^10.0|^11.0|^12.0
Requires (Dev)
- orchestra/testbench: ^8.0|^9.0
- phpunit/phpunit: ^10.0
This package is auto-updated.
Last update: 2025-12-19 04:08:48 UTC
README
English | 简体中文
A Laravel package for handling enums with frontend-friendly options (labels, colors, icons) and multi-language support.
Features
- 🎨 Frontend-Friendly: Built-in support for labels, colors, and icons
- 🌍 Multi-Language: Full i18n support with fallback mechanism
- 📦 Preset Enums: 10+ ready-to-use enum classes for common scenarios
- 🎯 Flexible: Use presets as-is, publish and customize, or create your own
- ⚙️ Configurable: Override labels and colors without modifying enum classes
- 🛠️ Artisan Commands: Generate, publish, and list enums with ease
- 🔄 Resource Integration: Works seamlessly with Laravel API Resources
Requirements
- PHP 8.1+
- Laravel 10.x, 11.x, or 12.x
Installation
Install the package via Composer:
composer require weijukeji/laravel-enum-options
Publish the configuration file (optional):
php artisan vendor:publish --tag=enum-options-config
Quick Start
Using Preset Enums
Use built-in preset enums directly:
use WeiJuKeJi\EnumOptions\Presets\Payment\PaymentMethodEnum; $method = PaymentMethodEnum::WECHAT; echo $method->label(); // 微信支付 echo $method->color(); // green echo $method->icon(); // wechat // Get all options for dropdown $options = PaymentMethodEnum::options(); // [ // ['value' => 'wechat', 'label' => '微信支付', 'color' => 'green', 'icon' => 'wechat'], // ['value' => 'alipay', 'label' => '支付宝', 'color' => 'blue', 'icon' => 'alipay'], // ... // ]
Publishing Presets to Your App
Publish preset enums to customize them:
# Publish a specific preset php artisan enum:publish PaymentMethod # Publish all presets php artisan enum:publish --all # Publish with translation files php artisan enum:publish PaymentMethod --with-translations
The enum will be published to app/Enums/PaymentMethodEnum.php and you can freely modify it.
Creating Custom Enums
Create your own enum from scratch:
php artisan make:enum SubscriptionStatus --values=active,paused,cancelled --labels
This generates:
<?php namespace App\Enums; use WeiJuKeJi\EnumOptions\Traits\EnumOptions; enum SubscriptionStatusEnum: string { use EnumOptions; case ACTIVE = 'active'; case PAUSED = 'paused'; case CANCELLED = 'cancelled'; public function label(): string { return $this->trans($this->value, match ($this) { self::ACTIVE => 'Active', self::PAUSED => 'Paused', self::CANCELLED => 'Cancelled', }); } public function color(): string { $configColor = config("enum-options.color_overrides.subscription_status.{$this->value}"); if ($configColor) { return $configColor; } return match ($this) { // TODO: Define colors for each case default => 'default', }; } }
Available Preset Enums
Payment
- PaymentMethodEnum: wechat, alipay, bank_transfer, cash, credit_card, debit_card, union_pay, paypal, apple_pay, google_pay, pos, wechat_pos, other
- PaymentStatusEnum: unpaid, pending, paying, paid, failed, cancelled, refunding, refunded, partially_refunded, timeout
- RefundStatusEnum: none, pending, processing, partial, full, failed, rejected
Order
- OrderStatusEnum: pending, confirmed, processing, completed, cancelled, expired, failed, on_hold, refunded, partially_refunded
- OrderTypeEnum: standard, presale, group_buy, flash_sale, subscription, gift, exchange
User
- UserStatusEnum: active, inactive, suspended, banned, deleted, pending_verification
- GenderEnum: male, female, other, prefer_not_to_say
Business
- ApprovalStatusEnum: draft, pending, approved, rejected, cancelled, revoked
- PublishStatusEnum: draft, scheduled, published, unpublished, archived
List Available Presets
# List all presets php artisan enum:list-presets # Show details of a specific preset php artisan enum:list-presets PaymentMethod # Output as JSON php artisan enum:list-presets --json
Usage in API Resources
Use enums in your API Resources to automatically format status fields:
use App\Enums\OrderStatusEnum; use App\Enums\PaymentMethodEnum; use Illuminate\Http\Resources\Json\JsonResource; class OrderResource extends JsonResource { public function toArray($request): array { return [ 'id' => $this->id, 'order_no' => $this->order_no, // Transform enum fields to objects with value, label, color 'status' => OrderStatusEnum::fromValue($this->status)?->toArray(), 'payment_method' => PaymentMethodEnum::fromValue($this->payment_method)?->toArray(), // Other fields... ]; } }
API Response:
{
"id": 1,
"order_no": "ORD20250118001",
"status": {
"value": "paid",
"label": "已支付",
"color": "green"
},
"payment_method": {
"value": "wechat",
"label": "微信支付",
"color": "green",
"icon": "wechat"
}
}
Configuration
Override Labels
Override labels without modifying enum classes:
// config/enum-options.php 'label_overrides' => [ 'payment_method' => [ 'wechat' => '微信', // Simplified label 'pos' => 'POS刷卡', // Custom terminology ], ],
Override Colors
// config/enum-options.php 'color_overrides' => [ 'payment_method' => [ 'wechat' => 'success', 'alipay' => 'primary', ], ],
Change Color Scheme
Support for different UI frameworks:
// config/enum-options.php 'color_scheme' => 'element-plus', // or 'ant-design', 'tailwind', 'bootstrap'
Multi-Language Support
Using Translation Files
Create translation files in your application:
// lang/zh-CN/enums.php return [ 'payment_method' => [ 'wechat' => '微信支付', 'alipay' => '支付宝', ], ];
Enums will automatically use these translations with fallback to preset translations.
Translation Priority
- User-defined translations (
lang/{locale}/enums.php) - Config overrides (
config/enum-options.php) - Package preset translations (
lang/{locale}/presets.php) - Default values in enum class
Advanced Usage
Get All Values
$values = PaymentMethodEnum::values(); // ['wechat', 'alipay', 'bank_transfer', ...]
Get All Labels
$labels = PaymentMethodEnum::labels(); // ['wechat' => '微信支付', 'alipay' => '支付宝', ...]
Validate Values
if (PaymentMethodEnum::isValid($input)) { $enum = PaymentMethodEnum::from($input); }
Safe Conversion
$enum = PaymentMethodEnum::fromValue($nullable); // Returns null if value is null or invalid
Safe Array Conversion with Fallback
When dealing with legacy data or external systems, you might have invalid enum values in your database. Use toArraySafe() to handle these gracefully without throwing exceptions:
// Safe conversion - returns fallback object for invalid values $result = PaymentStatusEnum::toArraySafe('old_invalid_status'); // Result: [ // 'value' => 'old_invalid_status', // 'label' => 'old_invalid_status', // or transformed based on config // 'color' => 'default', // 'icon' => null // ] // Use in API Resources to handle any value safely class OrderResource extends JsonResource { public function toArray($request): array { return [ 'id' => $this->id, // Will never throw exception even if status value is invalid 'status' => OrderStatusEnum::toArraySafe($this->status), ]; } }
Configure fallback behavior in config/enum-options.php:
// Fallback color for invalid values 'fallback_color' => 'default', // Label transformation strategy: none, upper, lower, ucfirst, ucwords 'fallback_label_transform' => 'ucwords', // 'old_status' -> 'Old Status' // Custom labels for specific invalid values 'fallback_labels' => [ 'legacy_paid' => 'Paid (Legacy)', 'unknown' => 'Unknown Status', ],
Automatic Enum Discovery
The package automatically discovers and registers enums without manual configuration.
How It Works
- Preset Enums: Automatically scanned from
src/Presetsdirectory - App Enums: Automatically scanned from
app/Enumsdirectory - No Maintenance Required: Just create enum files, they're discovered automatically
Adding New Enums
Simply create a new enum file with the EnumOptions trait:
// app/Enums/ShippingStatusEnum.php namespace App\Enums; use WeiJuKeJi\EnumOptions\Traits\EnumOptions; enum ShippingStatusEnum: string { use EnumOptions; case PENDING = 'pending'; case SHIPPED = 'shipped'; public function label(): string { return $this->value; } }
The enum is automatically registered and available via API without any configuration.
Configure Discovery
Control auto-discovery in config/enum-options.php:
// Auto-discover preset enums from src/Presets 'auto_discover_presets' => true, // Auto-discover app enums from app/Enums 'auto_discover_app_enums' => true, // Customize scan paths 'app_enums_paths' => [ app_path('Enums'), app_path('Domain/Shared/Enums'), // Additional paths ],
API Routes (Optional)
The package can automatically register API routes to provide enum options to your frontend.
Enable Auto Routes
Publish and edit the config file:
php artisan vendor:publish --tag=enum-options-config
Enable auto routes in config/enum-options.php:
'auto_register_routes' => true, 'route_prefix' => 'api/enums', 'route_middleware' => ['auth:sanctum'], 'route_name_prefix' => 'enums',
Available Endpoints
Routes are automatically generated for all registered enums! No manual maintenance required.
Once enabled, the following endpoints will be available:
GET /api/enums/list # Get metadata of all available enums GET /api/enums/all # Get all enum options (recommended) # Dynamically generated routes for all preset enums: GET /api/enums/payment-methods # Payment methods GET /api/enums/payment-statuses # Payment statuses GET /api/enums/refund-statuses # Refund statuses GET /api/enums/order-statuses # Order statuses GET /api/enums/order-types # Order types GET /api/enums/user-statuses # User statuses GET /api/enums/genders # Genders GET /api/enums/approval-statuses # Approval statuses GET /api/enums/publish-statuses # Publish statuses # Your custom enums are also automatically registered: GET /api/enums/shipping-statuses # If you have ShippingStatusEnum GET /api/enums/{your-custom-enum} # Any enum you create!
Key Features:
- ✅ Zero Configuration: Add a new enum, route is automatically created
- ✅ Dynamic Discovery: Uses EnumRegistry to find all enums
- ✅ Consistent URLs: Enum keys are converted to kebab-case (e.g.,
payment_methods→payment-methods) - ✅ Fully Scalable: Supports unlimited enums without code changes
Response Format
Enum List Endpoint (GET /api/enums/list):
Returns metadata about all available enums:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"key": "payment_methods",
"name": "Payment Methods",
"description": "All available payment method options",
"route": "/enums/payment-methods",
"count": 13,
"category": "payment"
}
],
"total": 9
}
}
Single Enum Endpoints (e.g., GET /api/enums/payment-methods):
Returns enum options in a standardized list format:
{
"code": 200,
"msg": "success",
"data": {
"list": [
{
"value": "wechat",
"label": "微信支付",
"color": "green",
"icon": "wechat"
},
{
"value": "alipay",
"label": "支付宝",
"color": "blue",
"icon": "alipay"
}
],
"total": 13
}
}
All Enums Endpoint (GET /api/enums/all):
Returns all enum options grouped by key:
{
"code": 200,
"msg": "success",
"data": {
"payment_methods": [...],
"payment_statuses": [...],
"order_statuses": [...]
}
}
The response format can be customized in config:
'response_format' => [ 'code_key' => 'code', 'message_key' => 'msg', 'data_key' => 'data', ],
Manual Route Registration
If you prefer manual control, keep auto_register_routes as false and register routes yourself.
Option 1: Dynamic Registration (Recommended)
Register routes dynamically using EnumRegistry:
// routes/api.php use WeiJuKeJi\EnumOptions\Http\Controllers\EnumController; use WeiJuKeJi\EnumOptions\Support\EnumRegistry; use Illuminate\Support\Str; Route::prefix('enums')->middleware('auth:sanctum')->group(function () { // Fixed routes Route::get('list', [EnumController::class, 'list']); Route::get('all', [EnumController::class, 'all']); // Dynamically register all enums foreach (EnumRegistry::all() as $key => $config) { Route::get(Str::kebab($key), [EnumController::class, 'show']) ->defaults('key', $key); } });
Option 2: Specific Routes
Register specific enum routes manually:
// routes/api.php use WeiJuKeJi\EnumOptions\Http\Controllers\EnumController; Route::prefix('enums')->middleware('auth:sanctum')->group(function () { Route::get('all', [EnumController::class, 'all']); // Specific enums using the dynamic show() method Route::get('payment-methods', [EnumController::class, 'show']) ->defaults('key', 'payment_methods'); Route::get('order-statuses', [EnumController::class, 'show']) ->defaults('key', 'order_statuses'); });
Option 3: Custom Controller
Create your own controller for custom response format:
namespace App\Http\Controllers; use WeiJuKeJi\EnumOptions\Support\EnumRegistry; class MyEnumController extends Controller { public function show(string $key) { $enumClass = EnumRegistry::getEnumClass($key); if (!$enumClass) { return response()->json(['error' => 'Not found'], 404); } return response()->json([ 'success' => true, 'data' => $enumClass::options(), ]); } }
Frontend Integration
Vue 3 Example
<template> <!-- Display with color --> <el-tag :type="order.status.color"> {{ order.status.label }} </el-tag> <!-- Dropdown selection --> <el-select v-model="filters.payment_method"> <el-option v-for="method in paymentMethods" :key="method.value" :value="method.value" :label="method.label" > <i :class="`icon-${method.icon}`" /> {{ method.label }} </el-option> </el-select> </template> <script setup> import { ref, onMounted } from 'vue' import axios from 'axios' const paymentMethods = ref([]) onMounted(async () => { // Fetch enum options from backend const { data } = await axios.get('/api/enums/payment-methods') paymentMethods.value = data.data.list // Access the list from response }) </script>
React Example
import { useEffect, useState } from 'react' function OrderList() { const [enums, setEnums] = useState({}) useEffect(() => { // Fetch all enums at once fetch('/api/enums/all') .then(res => res.json()) .then(data => setEnums(data.data)) }, []) return ( <div> {/* Display status with color */} <Badge color={order.status.color}> {order.status.label} </Badge> {/* Dropdown */} <Select> {enums.payment_methods?.map(method => ( <Option key={method.value} value={method.value}> {method.label} </Option> ))} </Select> </div> ) }
Testing
composer test
Changelog
Please see CHANGELOG for more information on what has changed recently.
Contributing
Please see CONTRIBUTING for details.
Security
If you discover any security-related issues, please email your.email@example.com instead of using the issue tracker.
Credits
License
The MIT License (MIT). Please see License File for more information.