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>
5.2 KiB
Executable File
5.2 KiB
Executable File
name, description
| name | description |
|---|---|
| polymorphic | RSX polymorphic relationships with type references storing integers instead of class names. Use when implementing morphTo relationships, defining type_ref_columns, handling polymorphic form fields, or using polymorphic join helpers. |
RSX Polymorphic Relationships
Overview
RSX uses a type reference system that stores integers in the database but transparently converts to/from class name strings in PHP.
$activity->eventable_type = 'Contact_Model'; // Stores integer in DB
echo $activity->eventable_type; // Returns "Contact_Model"
Benefits:
- Efficient integer storage (not VARCHAR class names)
- Automatic type discovery
- Transparent conversion
- Laravel morphTo() compatibility
Defining Type Reference Columns
Declare which columns are type references in your model:
class Activity_Model extends Rsx_Model_Abstract
{
protected static $type_ref_columns = ['eventable_type'];
public function eventable()
{
return $this->morphTo();
}
}
The cast is automatically applied - no manual $casts needed.
Database Schema
Type reference columns must be BIGINT, not VARCHAR:
CREATE TABLE activities (
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
eventable_type BIGINT NULL,
eventable_id BIGINT NULL,
action VARCHAR(50) NOT NULL,
INDEX idx_eventable (eventable_type, eventable_id)
);
Usage
Setting Values
$activity = new Activity_Model();
$activity->eventable_type = 'Contact_Model'; // Use class name
$activity->eventable_id = 123;
$activity->save();
Reading Values
echo $activity->eventable_type; // "Contact_Model" (string)
$related = $activity->eventable; // Returns Contact_Model instance
Querying
Class names are automatically converted to IDs in WHERE clauses:
// All work - class names auto-converted
Activity_Model::where('eventable_type', 'Contact_Model')->get();
Activity_Model::whereIn('eventable_type', ['Contact_Model', 'Project_Model'])->get();
Polymorphic Join Helpers
Join tables with polymorphic columns:
// INNER JOIN - contacts that have attachments
Contact_Model::query()
->joinMorph('file_attachments', 'fileable')
->select('contacts.*', 'file_attachments.filename')
->get();
// LEFT JOIN - all contacts, with attachments if they exist
Contact_Model::query()
->leftJoinMorph('file_attachments', 'fileable')
->get();
// RIGHT JOIN
Contact_Model::query()
->rightJoinMorph('file_attachments', 'fileable')
->get();
Parameters:
$table- Table with polymorphic columns (e.g., 'file_attachments')$morphName- Column prefix (e.g., 'fileable' for fileable_type/fileable_id)$morphClass- Optional explicit class (defaults to current model)
Form Handling
Client-Side Format
Polymorphic fields submit as JSON:
eventable={"model":"Contact_Model","id":123}
Server-Side Parsing
use App\RSpade\Core\Polymorphic_Field_Helper;
#[Ajax_Endpoint]
public static function save(Request $request, array $params = [])
{
$eventable = Polymorphic_Field_Helper::parse($params['eventable'], [
Contact_Model::class,
Project_Model::class,
]);
// Validate
if ($error = $eventable->validate('Please select an entity')) {
return response_error(Ajax::ERROR_VALIDATION, ['eventable' => $error]);
}
// Use
$activity = new Activity_Model();
$activity->eventable_type = $eventable->model; // "Contact_Model"
$activity->eventable_id = $eventable->id; // 123
$activity->save();
}
Important: Always use Model::class for the whitelist.
Auto-Discovery
When storing a new class name that isn't in _type_refs yet:
$attachment->fileable_type = 'Custom_Model';
$attachment->save();
RSX will:
- Verify
Custom_Modelexists and extendsRsx_Model_Abstract - Create a new
_type_refsentry with next available ID - Store that ID in the column
Any model can be used without pre-registration.
Common Patterns
File Attachments to Multiple Models
class File_Attachment_Model extends Rsx_Model_Abstract
{
protected static $type_ref_columns = ['fileable_type'];
public function fileable()
{
return $this->morphTo();
}
}
// Attach to contact
$attachment->fileable_type = 'Contact_Model';
$attachment->fileable_id = $contact->id;
// Attach to project
$attachment->fileable_type = 'Project_Model';
$attachment->fileable_id = $project->id;
Activity Log
class Activity_Model extends Rsx_Model_Abstract
{
protected static $type_ref_columns = ['subject_type'];
public function subject()
{
return $this->morphTo();
}
}
// Log activity for any model
Activity_Model::log('updated', $contact); // subject_type = 'Contact_Model'
Activity_Model::log('created', $project); // subject_type = 'Project_Model'
Simple Names Only
Always use simple class names (basename), never FQCNs:
// ✅ Correct
$activity->eventable_type = 'Contact_Model';
// ❌ Wrong - fully qualified
$activity->eventable_type = 'App\\Models\\Contact_Model';
More Information
Details: php artisan rsx:man polymorphic