Files
rspade_system/app/RSpade/man/model.txt
root f6fac6c4bc Fix bin/publish: copy docs.dist from project root
Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 02:08:33 +00:00

263 lines
8.4 KiB
Plaintext
Executable File

RSpade Models (Rsx_Model_Abstract)
OVERVIEW
All RSX models must extend Rsx_Model_Abstract, which provides:
- Enum system with magic properties and methods
- Mass assignment prevention (explicit field assignment only)
- Eager loading prevention (explicit queries only)
- Ajax ORM fetch() system
- Automatic boolean casting for TINYINT(1) columns
- Relationship management via #[Relationship] attribute
ENUM SYSTEM
Define enums using public static $enums property:
public static $enums = [
'status_id' => [
1 => ['constant' => 'STATUS_ACTIVE', 'label' => 'Active', 'order' => 1],
2 => ['constant' => 'STATUS_INACTIVE', 'label' => 'Inactive', 'order' => 2]
],
'role_id' => [
1 => ['constant' => 'ROLE_ADMIN', 'label' => 'Administrator'],
2 => ['constant' => 'ROLE_USER', 'label' => 'User']
]
];
Magic Properties (Instance):
- $model->status_id_label - Get label for current enum value
- $model->status_id_constant - Get constant name for current value
- $model->status_id_order - Get sort order for current value
- $model->status_id_enum_val - Get all properties for current value
Magic Methods (Static):
- Model::status_id_enum() - Get all enum definitions (sorted by 'order')
- Model::status_id_enum_select() - Get key/label pairs for dropdowns
- Model::status_id_enum_ids() - Get all possible enum values
Enum properties in $enums can include any custom keys (label, order, constant,
color, icon, etc.). All properties are exported to JavaScript via toArray().
Optional 'selectable' property (default true) controls dropdown visibility:
2 => ['constant' => 'STATUS_ARCHIVED', 'label' => 'Archived', 'selectable' => false]
MASS ASSIGNMENT PREVENTION
Mass assignment is explicitly prohibited. Use explicit field assignment:
// CORRECT
$model = new User_Model();
$model->name = $request->input('name');
$model->email = $request->input('email');
$model->save();
// WRONG - throws MassAssignmentException
$model = User_Model::create(['name' => 'John', 'email' => 'john@example.com']);
$model->fill(['name' => 'John']);
$model->update(['name' => 'John']);
Blocked methods: fill(), forceFill(), create(), firstOrCreate(), firstOrNew(),
updateOrCreate(), update()
EAGER LOADING PREVENTION
All forms of eager loading throw exceptions. Use explicit queries:
// WRONG - throws exception
$users = User_Model::with('posts')->get();
$user->load('posts');
// CORRECT - explicit queries
$users = User_Model::all();
foreach ($users as $user) {
$posts = Post_Model::where('user_id', $user->id)->get();
}
Rationale: Premature optimization is the root of all evil. When you have
thousands of concurrent users in production and N+1 queries become a real
bottleneck, you'll be motivated enough to remove these restrictions yourself.
AJAX ORM (Model Fetch System)
Models can opt-in to client-side fetching by implementing fetch() with
#[Ajax_Endpoint_Model_Fetch] attribute:
#[Ajax_Endpoint_Model_Fetch]
public static function fetch($id)
{
// Check authorization
if (!RsxAuth::check()) {
return false;
}
// Fetch single record
$model = static::find($id);
return $model ?: false;
}
JavaScript usage:
const product = await Product_Model.fetch(1);
const products = await Product_Model.fetch([1, 2, 3]);
Framework automatically splits array IDs into individual fetch() calls for
security (no mass fetching).
See: php artisan rsx:man model_fetch
RELATIONSHIPS
Define relationships using #[Relationship] attribute to prevent Laravel from
auto-detecting non-relationship methods:
#[Relationship]
public function posts()
{
return $this->hasMany(Post_Model::class);
}
Only methods with #[Relationship] are considered relationships. This prevents
methods like is_active() from being mistaken for relationships.
Note: Eager loading is still blocked. Relationships are supported but must be
loaded with explicit queries.
AUTOMATIC BOOLEAN CASTING
TINYINT(1) columns are automatically cast to boolean without manual $casts
definition. Framework consults manifest database metadata to detect boolean
columns at runtime.
Manual $casts entries take precedence over automatic detection.
NEVER EXPORT FIELDS
Exclude sensitive fields from toArray() and Ajax responses:
protected $neverExport = ['password', 'api_token', 'remember_token'];
Fields in $neverExport are automatically removed before JavaScript export.
UTILITY METHODS
Static Methods:
- get_table_static() - Get table name without instantiating model
- getColumns() - Get array of column names for model's table
- hasColumn($column) - Check if column exists
- get_relationships() - Get array of relationship method names
- clear_table_cache() - Clear query cache for table
- clear_all_caches() - Clear all query caches
Instance Methods:
- make_new() - Create new model instance (recommended over new Model())
- get_mass_assignment_example() - Get helpful example code for this model
MODEL ORGANIZATION WITH TRAITS
Large models can be split into domain-specific trait files. This organization
strategy is primarily designed for models, though traits can be used elsewhere
in RSX applications.
Naming Convention:
Trait files should be prefixed with the model name they elaborate on:
Users_Model -> Users_Model_Authentication (trait for auth methods)
Users_Model -> Users_Model_Relationships (trait for relationship methods)
Users_Model -> Users_Model_Permissions (trait for permission logic)
This makes it immediately clear which model a trait belongs to.
Organization Strategy:
Group methods by problem domain within separate trait files:
- Authentication/authorization logic
- Query methods for specific use cases
- Relationship definitions
- Business logic for specific features
- Computed properties and accessors
Example Implementation:
// rsx/models/traits/users_model_authentication.php
trait Users_Model_Authentication
{
public static function find_by_email(string $email)
{
return static::where('email', $email)->first();
}
public static function find_by_api_token(string $token)
{
return static::where('api_token', $token)->first();
}
public function verify_password(string $password): bool
{
return password_verify($password, $this->password);
}
}
// rsx/models/traits/users_model_relationships.php
trait Users_Model_Relationships
{
#[Relationship]
public function posts()
{
return $this->hasMany(Posts_Model::class);
}
#[Relationship]
public function profile()
{
return $this->hasOne(User_Profiles_Model::class);
}
}
// rsx/models/users_model.php
class Users_Model extends Rsx_Model_Abstract
{
use Users_Model_Authentication;
use Users_Model_Relationships;
protected $table = 'users';
public static $enums;
protected $neverExport = ['password', 'api_token'];
}
Manifest Integration:
The manifest system automatically discovers and indexes methods from traits:
- Trait files are loaded before classes during manifest build
- Methods from traits appear in the model's metadata
- IDE helpers correctly locate trait method definitions
- Code quality rules validate trait methods same as class methods
Benefits:
- Keep models focused and maintainable
- Group related functionality by problem domain
- Easier to navigate large models with hundreds of methods
- Clear separation between different aspects of model behavior
- Traits are discovered and validated automatically by manifest
NAMING CONVENTIONS
Tables:
- Plural snake_case (users, user_logins, product_categories)
- Always include 'id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY'
Columns:
- snake_case for all column names
- Foreign keys must suffix with '_id' (user_id, site_id)
- Booleans must prefix with 'is_' (is_active, is_published)
- Timestamps must suffix with '_at' (created_at, updated_at, deleted_at)
- Use BIGINT for all integers, TINYINT(1) for booleans only
- All text columns use UTF-8 (utf8mb4_unicode_ci collation)
SEE ALSO
php artisan rsx:man model_fetch - Ajax ORM fetch system
php artisan rsx:man model_normalization - Database normalization process
php artisan rsx:man enums - Complete enum system documentation
php artisan rsx:man migrations - Migration system and safety