Add form value persistence across cache revalidation re-renders 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
6.2 KiB
Executable File
name, description
| name | description |
|---|---|
| model-enums | 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
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:
'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
// 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
project.status_id = Project_Model.STATUS_ACTIVE;
Instance Property Access
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()):
// 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
<span class="badge <%= this.args.project.status_id__badge %>">
<%= this.args.project.status_id__label %>
</span>
<Select_Input
$name="status_id"
$options="<%= JSON.stringify(Project_Model.status_id__enum_select()) %>"
/>
Boolean Fields
For boolean fields, use 0/1 as keys:
'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:
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:
'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],
],
]
// 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:
// 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:
$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:
php artisan rsx:migrate:document_models
This updates the model's documentation comments with enum information.
More Information
Details: php artisan rsx:man enum