--- name: model-enums description: Implementing model enums in RSX with integer-backed values, constants, labels, and custom properties. Use when adding enum fields to models, working with status_id or type_id columns, accessing enum labels/properties via BEM-style syntax, or populating dropdowns with enum values. --- # RSX Model Enums Integer-backed enums with model-level mapping to constants, labels, and custom properties. Uses BEM-style double underscore naming for magic properties. ## Defining Enums ```php class Project_Model extends Rsx_Model_Abstract { public static $enums = [ 'status_id' => [ 1 => ['constant' => 'STATUS_ACTIVE', 'label' => 'Active', 'badge' => 'bg-success', 'order' => 1], 2 => ['constant' => 'STATUS_ON_HOLD', 'label' => 'On Hold', 'badge' => 'bg-warning', 'order' => 2], 3 => ['constant' => 'STATUS_ARCHIVED', 'label' => 'Archived', 'selectable' => false, 'order' => 99], ], 'priority_id' => [ 1 => ['constant' => 'PRIORITY_LOW', 'label' => 'Low', 'color' => '#999', 'days' => 30], 2 => ['constant' => 'PRIORITY_MEDIUM', 'label' => 'Medium', 'color' => '#f90', 'days' => 14], 3 => ['constant' => 'PRIORITY_HIGH', 'label' => 'High', 'color' => '#f00', 'days' => 7], ], ]; } ``` ## Required Properties | Property | Purpose | |----------|---------| | `constant` | Static constant name (generates `Model::STATUS_ACTIVE`) | | `label` | Human-readable display text | ## Special Properties | Property | Default | Purpose | |----------|---------|---------| | `order` | 0 | Sort position in dropdowns (lower first) | | `selectable` | true | Include in dropdown options | Non-selectable items are excluded from `field__enum_select()` but still display correctly when they're the current value. ## Custom Properties Add any properties for business logic - they become accessible via BEM-style syntax: ```php 'status_id' => [ 1 => [ 'constant' => 'STATUS_ACTIVE', 'label' => 'Active', 'badge' => 'bg-success', // CSS class 'icon' => 'fa-check', // Icon class 'can_edit' => true, // Business rule 'permissions' => ['edit', 'view'], // Permission list ], ], ``` --- ## PHP Usage ```php // Set using constant $project->status_id = Project_Model::STATUS_ACTIVE; // BEM-style property access (field__property) echo $project->status_id__label; // "Active" echo $project->status_id__badge; // "bg-success" echo $project->status_id__icon; // "fa-check" // Business logic flags if ($project->status_id__can_edit) { // Allow editing } ``` --- ## JavaScript Usage ### Static Constants ```javascript project.status_id = Project_Model.STATUS_ACTIVE; ``` ### Instance Property Access ```javascript const project = await Project_Model.fetch(1); console.log(project.status_id__label); // "Active" console.log(project.status_id__badge); // "bg-success" ``` ### Static Enum Methods All use BEM-style double underscore (`field__method()`): ```javascript // Get all enum data Project_Model.status_id__enum() // Returns: {1: {label: 'Active', badge: 'bg-success', ...}, 2: {...}, ...} // Get specific enum's metadata by ID Project_Model.status_id__enum(Project_Model.STATUS_ACTIVE) // Returns: {label: 'Active', badge: 'bg-success', order: 1, ...} Project_Model.status_id__enum(2).selectable // true or false // For dropdown population (respects 'selectable' and 'order') Project_Model.status_id__enum_select() // Returns: [{value: 1, label: 'Active'}, {value: 2, label: 'On Hold'}] // Note: Archived excluded because selectable: false // Simple id => label map Project_Model.status_id__enum_labels() // Returns: {1: 'Active', 2: 'On Hold', 3: 'Archived'} // Array of valid IDs Project_Model.status_id__enum_ids() // Returns: [1, 2, 3] ``` --- ## Template Usage ```jqhtml <%= this.args.project.status_id__label %> ``` --- ## Boolean Fields For boolean fields, use 0/1 as keys: ```php 'is_verified' => [ 0 => ['constant' => 'NOT_VERIFIED', 'label' => 'Not Verified', 'icon' => 'fa-times'], 1 => ['constant' => 'VERIFIED', 'label' => 'Verified', 'icon' => 'fa-check'], ] ``` --- ## Context-Specific Labels Define different labels for different contexts: ```php 1 => [ 'constant' => 'STATUS_NEW', 'label' => 'New Listing', // Backend/default 'label_frontend' => 'Coming Soon', // Public-facing 'label_short' => 'New', // Abbreviated ] ``` Access: `$item->status__label_frontend` --- ## Permission Systems Use custom properties for complex permission logic: ```php 'role_id' => [ 1 => [ 'constant' => 'ROLE_ADMIN', 'label' => 'Administrator', 'permissions' => ['users.create', 'users.delete', 'settings.edit'], 'can_admin_roles' => [2, 3, 4], // Can manage these role IDs ], 2 => [ 'constant' => 'ROLE_MANAGER', 'label' => 'Manager', 'permissions' => ['users.view', 'reports.view'], 'can_admin_roles' => [3, 4], ], ] ``` ```php // Check permissions if (in_array('users.create', $user->role_id__permissions)) { // User can create users } ``` --- ## Anti-Aliasing Policy **NEVER alias enum properties in fetch()** - the BEM-style naming exists for grepability: ```php // WRONG - Aliasing obscures data source $data['type_label'] = $record->type_id__label; // BAD // RIGHT - Use full BEM-style names in JavaScript contact.type_id__label // Good - grepable, self-documenting ``` The `fetch()` function's purpose is SECURITY (removing private data), not aliasing. --- ## Database Migration **Always use BIGINT for enum columns:** ```php $table->bigInteger('status_id')->default(Project_Model::STATUS_ACTIVE); ``` **Never use:** - VARCHAR (wastes space) - MySQL ENUM type (inflexible) - TINYINT (too small for future expansion) --- ## After Adding Enums Run model documentation generator: ```bash php artisan rsx:migrate:document_models ``` This updates the model's documentation comments with enum information. ## More Information Details: `php artisan rsx:man enum`