Polymorphic Relations
The variableMorphs() macro eliminates verbose match expressions when defining polymorphic relationship columns, making your migrations cleaner and type-safe.
Basic Usage
Section titled “Basic Usage”use Cline\VariableKeys\Enums\MorphType;use Illuminate\Database\Schema\Blueprint;use Illuminate\Support\Facades\Schema;
Schema::create('comments', function (Blueprint $table) { $table->id(); $table->text('body');
// Polymorphic relationship $table->variableMorphs('commentable', MorphType::ULID);
$table->timestamps();});Method Signature
Section titled “Method Signature”$table->variableMorphs(string $name, MorphType $type, bool $nullable = false)Parameters:
$name- The morph relationship name (e.g.,'commentable','taggable')$type- The morph type enum value$nullable- Whether the relationship is optional (default:false)
Available Morph Types
Section titled “Available Morph Types”String (Auto-Detected)
Section titled “String (Auto-Detected)”Laravel’s default morphs that automatically detect the appropriate column type.
$table->variableMorphs('commentable', MorphType::String);Equivalent to:
$table->morphs('commentable');Numeric (Integer IDs)
Section titled “Numeric (Integer IDs)”Explicitly use integer foreign keys for the morph relationship. Best when models use auto-incrementing integer primary keys.
$table->variableMorphs('taggable', MorphType::Numeric);Equivalent to:
$table->numericMorphs('taggable');Use 36-character UUIDs for the morph relationship.
$table->variableMorphs('imageable', MorphType::UUID);Equivalent to:
$table->uuidMorphs('imageable');Use 26-character ULIDs for the morph relationship.
$table->variableMorphs('attachable', MorphType::ULID);Equivalent to:
$table->ulidMorphs('attachable');Nullable Relationships
Section titled “Nullable Relationships”Set the third parameter to true for optional polymorphic relationships:
$table->variableMorphs('parent', MorphType::UUID, nullable: true);This creates nullable columns for both the type and ID:
// Equivalent to:$table->nullableUuidMorphs('parent');Configuration-Driven Morphs
Section titled “Configuration-Driven Morphs”Centralize your morph type configuration:
return [ 'morph_type' => env('DB_MORPH_TYPE', 'string'),];Use in migrations:
use Cline\VariableKeys\Enums\MorphType;
$morphType = MorphType::tryFrom(config('database.morph_type')) ?? MorphType::String;
Schema::create('images', function (Blueprint $table) use ($morphType) { $table->id(); $table->string('url');
$table->variableMorphs('imageable', $morphType);
$table->timestamps();});Before and After
Section titled “Before and After”Before: Verbose Match Expression
Section titled “Before: Verbose Match Expression”match ($morphType) { MorphType::ULID => $table->ulidMorphs('commentable'), MorphType::UUID => $table->uuidMorphs('commentable'), MorphType::Numeric => $table->numericMorphs('commentable'), MorphType::String => $table->morphs('commentable'),};After: Clean Macro
Section titled “After: Clean Macro”$table->variableMorphs('commentable', $morphType);Examples
Section titled “Examples”Comments System with ULIDs
Section titled “Comments System with ULIDs”use Cline\VariableKeys\Enums\MorphType;
Schema::create('comments', function (Blueprint $table) { $table->ulid('id')->primary(); $table->text('body'); $table->foreignUlid('user_id')->constrained()->cascadeOnDelete();
// Comments can belong to posts, videos, etc. $table->variableMorphs('commentable', MorphType::ULID);
$table->timestamps();});Tagging System with Numeric IDs
Section titled “Tagging System with Numeric IDs”Schema::create('taggables', function (Blueprint $table) { $table->id();
$table->foreignId('tag_id')->constrained()->cascadeOnDelete();
// Tags can be attached to posts, products, etc. $table->variableMorphs('taggable', MorphType::Numeric);
$table->unique(['tag_id', 'taggable_type', 'taggable_id']); $table->timestamps();});Media Library with UUIDs
Section titled “Media Library with UUIDs”Schema::create('media', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('file_name'); $table->string('mime_type'); $table->unsignedBigInteger('size');
// Media can be attached to users, posts, products, etc. $table->variableMorphs('mediable', MorphType::UUID);
$table->timestamps();});Activity Log with Nullable Subject
Section titled “Activity Log with Nullable Subject”Schema::create('activity_log', function (Blueprint $table) { $table->id(); $table->string('description');
$table->variableMorphs('causer', MorphType::ULID);
// Subject is optional (some activities don't have a subject) $table->variableMorphs('subject', MorphType::ULID, nullable: true);
$table->timestamps();});Notification System
Section titled “Notification System”Schema::create('notifications', function (Blueprint $table) { $table->uuid('id')->primary(); $table->string('type'); $table->text('data');
// The entity that can receive notifications $table->variableMorphs('notifiable', MorphType::UUID);
$table->timestamp('read_at')->nullable(); $table->timestamps();});Choosing the Right Morph Type
Section titled “Choosing the Right Morph Type”| Type | Use When | Characteristics |
|---|---|---|
| String | Default, flexible setup | Auto-detects column type |
| Numeric | Integer primary keys | Efficient, traditional IDs |
| UUID | UUID primary keys | Globally unique, random |
| ULID | ULID primary keys | Sortable, time-ordered |
Relationship Configuration
Section titled “Relationship Configuration”After creating the morph columns in your migration, define the relationship in your models:
use Illuminate\Database\Eloquent\Model;use Illuminate\Database\Eloquent\Relations\MorphTo;
class Comment extends Model{ public function commentable(): MorphTo { return $this->morphTo(); }}
class Post extends Model{ public function comments(): MorphMany { return $this->morphMany(Comment::class, 'commentable'); }}