### Install Parental Package Source: https://github.com/tightenco/parental/blob/main/readme.md Use Composer to add the Parental package to your Laravel project. ```bash composer require tightenco/parental ``` -------------------------------- ### Create and Retrieve Child Model Instances Source: https://github.com/tightenco/parental/blob/main/readme.md Create new records that will be automatically typed as specific child models, and retrieve all users, getting back instances of their respective child types. ```php use App\Models\Admin; use App\Models\Guest; use App\Models\User; // Adds row to "users" table with "type" column set to: "App/Admin" Admin::create(...); // Adds row to "users" table with "type" column set to: "App/Guest" Guest::create(...); // Returns 2 model instances: Admin, and Guest User::all(); ``` -------------------------------- ### Configure Type Aliases with $childTypes Source: https://context7.com/tightenco/parental/llms.txt Override the default behavior of storing fully-qualified class names in the `type` column by mapping short string aliases (or Enum values) to child classes on the parent model. This example uses a backed Enum for type aliases. ```php use Parental\Tests\Enums\ToolNames; // BackedEnum class Tool extends Model { use HasChildren; protected $childTypes = [ ToolNames::ClawHammer->value => ClawHammer::class, // 'claw_hammer' ToolNames::Mallet->value => Mallet::class, // 'mallet' ToolNames::SledgeHammer->value => SledgeHammer::class, ]; } // Creates row with type = 'claw_hammer' (alias, not full class name) $hammer = ClawHammer::create(); echo $hammer->fresh()->type; // "claw_hammer" // Hydrates correct child class when reading back $tools = Tool::all(); // $tools[0] instanceof ClawHammer => true // $tools[1] instanceof Mallet => true ``` -------------------------------- ### Transform Model Type using become() Source: https://github.com/tightenco/parental/blob/main/readme.md Change a model instance from one type to another (e.g., from PendingOrder to ShippedOrder) using the `become()` method and save the changes. ```php use App\Models\Order; use App\Models\ShippedOrder; // Retrieve a pending order $order = Order::first(); // Ship the order by transforming it $order = $order->become(ShippedOrder::class); // Updates the "type" column to "shipped" and returns a ShippedOrder instance $order->save(); ``` -------------------------------- ### Register Parental Nova Resource Provider Source: https://github.com/tightenco/parental/blob/main/readme.md To enable shared parent Nova resources with child models, register the `NovaResourceProvider` within your `NovaServiceProvider`'s boot method. This ensures proper Nova integration. ```php class NovaServiceProvider extends NovaApplicationServiceProvider { public function boot() { parent::boot(); // ... $this->app->register( Parental\Providers\NovaResourceProvider::class ); } } ``` -------------------------------- ### Define Multiple Child Models Source: https://github.com/tightenco/parental/blob/main/readme.md Set up different child models that inherit from the same parent, each using the HasParent trait. ```php namespace App\Models; use Parental\HasParent; // A "child" class Admin extends User { use HasParent; } namespace App\Models; use Parental\HasParent; // Another "child" class Guest extends User { use HasParent; } ``` -------------------------------- ### Listen to Model Becoming Event Source: https://github.com/tightenco/parental/blob/main/readme.md Listen for the `becoming` event to perform actions before a model is saved during a type transition. This event is fired when a model is about to change its type. ```php ShippedOrder::becoming(function ($shippedOrder) { // Do something before the model is saved... }); ``` -------------------------------- ### Define Order Hierarchy with Child Types Source: https://github.com/tightenco/parental/blob/main/readme.md Establish a model hierarchy for orders, defining different types like 'pending' and 'shipped' using `$childTypes`. ```php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; use Parental\HasParent; class Order extends Model { use HasChildren; protected $fillable = ['type', 'total']; protected $childTypes = [ 'pending' => PendingOrder::class, 'shipped' => ShippedOrder::class, ]; } class PendingOrder extends Order { use HasParent; } class ShippedOrder extends Order { use HasParent; } ``` -------------------------------- ### `become()` — Transform a Model Between Types Source: https://context7.com/tightenco/parental/llms.txt Converts a model instance to a different child (or parent) type, preserving all attributes and loaded relationships. Returns the new instance; call `save()` to persist the type change. ```APIDOC ## `become()` — Transform a Model Between Types Converts a model instance to a different child (or parent) type, preserving all attributes and loaded relationships. Returns the new instance; call `save()` to persist the type change. ```php use App\Models\PendingOrder; use App\Models\ShippedOrder; $pending = PendingOrder::find(1); // $pending->type => 'pending' $shipped = $pending->become(ShippedOrder::class); // $shipped->type => 'shipped' // $shipped->id === $pending->id (same record) // $shipped->total === $pending->total (attributes preserved) // $shipped->exists === true // $shipped->getConnectionName() === $pending->getConnectionName() $shipped->save(); // Persists the type column change to the database ``` ``` -------------------------------- ### Eager Load Child Model Relationships from Instance Source: https://github.com/tightenco/parental/blob/main/readme.md Eager-load relationships for different child model types from a single parent model instance using `loadChildren`. This method takes an array where keys are child model classes and values are the relationships to load. ```php $message = Message::first(); $message->loadChildren([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ]); ``` -------------------------------- ### Eager Load Child Relationships from Query Source: https://github.com/tightenco/parental/blob/main/readme.md Use `childrenWith` to eager-load specific relationships for different child model types directly from a query. Ensure the child models are correctly mapped. ```php Message::query()->childrenWith([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ])->get(); ``` -------------------------------- ### Access Child Model Instance Source: https://github.com/tightenco/parental/blob/main/readme.md Retrieve an instance of a child model, which will be mapped to the parent's table. ```php use App\Models\Admin; // Returns "Admin" model, but reference "users" table: $admin = Admin::first(); // Can now access behavior exclusive to "Admin"s $admin->impersonate($user); ``` -------------------------------- ### `becoming` Model Event — Hook Into Type Transitions Source: https://context7.com/tightenco/parental/llms.txt Listen to the `becoming` event to run logic just before a model's type changes. Register via static callback or Laravel's `Event` facade. ```APIDOC ## `becoming` Model Event — Hook Into Type Transitions Listen to the `becoming` event to run logic just before a model's type changes. Register via static callback or Laravel's `Event` facade. ```php use App\Models\ShippedOrder; // Using static callback ShippedOrder::becoming(function (ShippedOrder $order) { // Notify shipping department before the type is saved \Log::info("Order #{$order->id} is being shipped."); }); // Using the Event facade \Illuminate\Support\Facades\Event::listen( 'eloquent.becoming: ' . ShippedOrder::class, function (ShippedOrder $order) { // Send shipping confirmation email \Mail::to($order->customer_email)->send(new ShippingConfirmation($order)); } ); // Both listeners fire when become() is called $shipped = $pending->become(ShippedOrder::class); $shipped->save(); ``` ``` -------------------------------- ### Parent Model with Fillable Type Source: https://github.com/tightenco/parental/blob/main/readme.md Configure the parent model to allow mass assignment for the 'type' column. ```php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; // The "parent" class User extends Model { use HasChildren; protected $fillable = ['type']; } ``` -------------------------------- ### Hook into Model Type Transitions with `becoming` Event Source: https://context7.com/tightenco/parental/llms.txt Listen to the `becoming` event to execute logic just before a model's type is changed. This can be registered using a static callback on the model or via Laravel's `Event` facade. ```php use App\Models\ShippedOrder; // Using static callback ShippedOrder::becoming(function (ShippedOrder $order) { // Notify shipping department before the type is saved \Log::info("Order #{$order->id} is being shipped."); }); // Using the Event facade \Illuminate\Support\Facades\Event::listen( 'eloquent.becoming: ' . ShippedOrder::class, function (ShippedOrder $order) { // Send shipping confirmation email \Mail::to($order->customer_email)->send(new ShippingConfirmation($order)); } ); // Both listeners fire when become() is called $shipped = $pending->become(ShippedOrder::class); $shipped->save(); ``` -------------------------------- ### Define Parent Model with HasChildren Source: https://github.com/tightenco/parental/blob/main/readme.md Set up the base model to utilize Single Table Inheritance by using the HasChildren trait. ```php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; // The "parent" class User extends Model { use HasChildren; // } ``` -------------------------------- ### Register NovaResourceProvider in Laravel Nova Source: https://context7.com/tightenco/parental/llms.txt Register the built-in NovaResourceProvider at the end of the boot() method in NovaServiceProvider to enable sharing Nova resources across parent and child models. This ensures that Nova resources are already loaded before the provider is registered. ```php // app/Providers/NovaServiceProvider.php namespace App\Providers; use Laravel\Nova\NovaApplicationServiceProvider; use Parental\Providers\NovaResourceProvider; class NovaServiceProvider extends NovaApplicationServiceProvider { public function boot(): void { parent::boot(); // Register at the END of boot() so Nova resources are already loaded $this->app->register(NovaResourceProvider::class); } } ``` -------------------------------- ### Eager Load Child Relationships from Relationship Source: https://github.com/tightenco/parental/blob/main/readme.md When working with a parent model that has a relationship to child models, you can use `childrenWith` on that relationship to eager-load specific child relationships. This is useful for fetching related data efficiently. ```php class Room extends Model { public function messages(): HasMany { return $this->hasMany(Message::class); } } ``` ```php $room = Room::first(); $messages = $room->messages()->childrenWith([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ])->get(); ``` -------------------------------- ### Eager Load Child Relationship Counts from Relationship Source: https://github.com/tightenco/parental/blob/main/readme.md Apply `childrenWithCount` to a parent model's relationship to eager-load relationship counts for child models. This is efficient for displaying counts alongside child data. ```php $room = Room::first(); $messages = $room->messages()->childrenWithCount([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ])->get(); ``` -------------------------------- ### Eager Load Child Relationship Counts from Query Source: https://github.com/tightenco/parental/blob/main/readme.md Utilize `childrenWithCount` to eager-load the count of specific relationships for different child model types from a query. This populates `_count` attributes on the child models. ```php $messages = Message::query()->childrenWithCount([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ])->get(); ``` -------------------------------- ### Define Child Model with HasParent Source: https://github.com/tightenco/parental/blob/main/readme.md Extend the parent model and use the HasParent trait to create a specific child model. ```php namespace App\Models; use Parental\HasParent; // The "child" class Admin extends User { use HasParent; public function impersonate($user) { //... } } ``` -------------------------------- ### `childrenWith()` / `childrenWithCount()` Query Scopes — Eager Load From Query (Laravel 11+) Source: https://context7.com/tightenco/parental/llms.txt Apply eager loading of child-specific relationships directly from a query builder or a relationship query. ```APIDOC ## `childrenWith()` / `childrenWithCount()` Query Scopes — Eager Load From Query (Laravel 11+) Apply eager loading of child-specific relationships directly from a query builder or a relationship query. ```php // From a query builder $messages = Message::query()->childrenWith([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ])->get(); foreach ($messages as $message) { if ($message instanceof TextMessage) { echo $message->images->count(); // loaded } elseif ($message instanceof VideoMessage) { echo $message->video->url; // loaded } } // From a relationship query $room = Room::find(1); $messages = $room->messages()->childrenWith([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ])->get(); // Count variant from a relationship $messages = $room->messages()->childrenWithCount([ TextMessage::class => ['images'], ])->get(); $textMsg = $messages->first(fn ($m) => $m instanceof TextMessage); echo $textMsg->images_count; // e.g. 2 $videoMsg = $messages->first(fn ($m) => $m instanceof VideoMessage); echo $videoMsg->images_count; // null — not loaded for this type ``` ``` -------------------------------- ### Eager Load Child Relationships from Query with `childrenWith()` Source: https://context7.com/tightenco/parental/llms.txt Apply eager loading of child-specific relationships directly from a query builder or a relationship query. This functionality is available in Laravel 11+. ```php // From a query builder $messages = Message::query()->childrenWith([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ])->get(); foreach ($messages as $message) { if ($message instanceof TextMessage) { echo $message->images->count(); // loaded } elseif ($message instanceof VideoMessage) { echo $message->video->url; // loaded } } // From a relationship query $room = Room::find(1); $messages = $room->messages()->childrenWith([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ])->get(); // Count variant from a relationship $messages = $room->messages()->childrenWithCount([ TextMessage::class => ['images'], ])->get(); $textMsg = $messages->first(fn ($m) => $m instanceof TextMessage); echo $textMsg->images_count; // e.g. 2 $videoMsg = $messages->first(fn ($m) => $m instanceof VideoMessage); echo $videoMsg->images_count; // null — not loaded for this type ``` -------------------------------- ### Define Child Model Relationships Source: https://github.com/tightenco/parental/blob/main/readme.md Define the parent and child model structure using `HasChildren` and `HasParent` traits. Specify the different child types a parent model can have using the `$childTypes` property. ```php class Message extends Model { use HasChildren; protected $fillable = ['type', 'content']; protected $childTypes = [ 'text' => TextMessage::class, 'image' => ImageMessage::class, ]; } class TextMessage extends Message { use HasParent; public function mentions(): HasMany { return $this->hasMany(User::class); } } class ImageMessage extends Message { use HasParent; public function attachments(): HasMany { return $this->hasMany(Attachment::class); } } ``` -------------------------------- ### Eager Load Relationships on Model Instances with `loadChildren()` Source: https://context7.com/tightenco/parental/llms.txt Eagerly load relationships on a single model instance or an Eloquent collection, dispatching to the correct relationship based on the actual child class type. This feature is available in Laravel 11+. ```php // On a single model instance $message = Message::find(1); // Could be TextMessage or VideoMessage $message->loadChildren([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ]); // If $message is a TextMessage, 'images' is loaded // If $message is a VideoMessage, 'video' is loaded // Count variant $message->loadChildrenCount([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ]); echo $message->images_count; // e.g. 3 (only set if TextMessage) // On a collection $messages = Message::all(); $messages->loadChildren([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ]); // Each model in the collection gets its own type-appropriate relationships loaded ``` -------------------------------- ### Parent Observers and Events Apply to Children Source: https://context7.com/tightenco/parental/llms.txt Observers and model events registered on a parent model automatically apply to all its child models. Events registered on a child model only affect that specific child type. ```php // VehicleObserver is automatically applied to Car, Plane, Train, etc. Vehicle::observe(VehicleObserver::class); $car = Car::create(); // VehicleObserver::creating() fires $plane = Plane::create(); // VehicleObserver::creating() fires // Register an event directly on the parent — propagates to all children Vehicle::created(function ($vehicle) { \Log::info(get_class($vehicle) . ' was created with id ' . $vehicle->id); }); $car = Car::create(); // Logs "Car was created with id 1" // Register an event on a child — does NOT affect parent or siblings Car::created(function ($car) { $car->driver_id = 99; }); $plane = Plane::create(); // $plane->driver_id is NOT set; the Car listener did not fire ``` -------------------------------- ### Eager Load Child Model Relationship Counts from Instance Source: https://github.com/tightenco/parental/blob/main/readme.md Eager-load the count of relationships for different child model types from a single parent model instance using `loadChildrenCount`. This is useful for displaying counts without loading the actual related models. ```php $message = Message::first(); $message->loadChildrenCount([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ]); ``` -------------------------------- ### Configure Type Aliases for Child Models Source: https://github.com/tightenco/parental/blob/main/readme.md Customize the values stored in the 'type' column by defining a `$childTypes` property on the parent model, mapping aliases to full class names. ```php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; class User extends Model { use HasChildren; protected $fillable = ['type']; protected $childTypes = [ 'admin' => Admin::class, 'guest' => Guest::class, ]; } ``` -------------------------------- ### Eager Load Child Model Relationships from Collection Source: https://github.com/tightenco/parental/blob/main/readme.md Eager-load relationships for child models within an Eloquent Collection using `loadChildren`. This applies the eager loading logic to each child model in the collection based on its type. ```php $messages = Message::all(); $messages->loadChildren([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ]); ``` -------------------------------- ### `loadChildren()` / `loadChildrenCount()` — Eager Load on Model Instances (Laravel 11+) Source: https://context7.com/tightenco/parental/llms.txt Eager-load relationships on a single model instance or an Eloquent collection, dispatching to the correct relationship based on the actual child class type. ```APIDOC ## `loadChildren()` / `loadChildrenCount()` — Eager Load on Model Instances (Laravel 11+) Eager-load relationships on a single model instance or an Eloquent collection, dispatching to the correct relationship based on the actual child class type. ```php // On a single model instance $message = Message::find(1); // Could be TextMessage or VideoMessage $message->loadChildren([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ]); // If $message is a TextMessage, 'images' is loaded // If $message is a VideoMessage, 'video' is loaded // Count variant $message->loadChildrenCount([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ]); echo $message->images_count; // e.g. 3 (only set if TextMessage) // On a collection $messages = Message::all(); $messages->loadChildren([ TextMessage::class => ['images'], VideoMessage::class => ['video'], ]); // Each model in the collection gets its own type-appropriate relationships loaded ``` ``` -------------------------------- ### Observer & Event Propagation — Parent Events Apply to Children Source: https://context7.com/tightenco/parental/llms.txt Observers and model events registered on the parent automatically apply to all child models. Events registered on a child only affect that specific child type. ```APIDOC ## Observer & Event Propagation — Parent Events Apply to Children Observers and model events registered on the parent automatically apply to all child models. Events registered on a child only affect that specific child type. ```php // VehicleObserver is automatically applied to Car, Plane, Train, etc. Vehicle::observe(VehicleObserver::class); $car = Car::create(); // VehicleObserver::creating() fires $plane = Plane::create(); // VehicleObserver::creating() fires // Register an event directly on the parent — propagates to all children Vehicle::created(function ($vehicle) { \Log::info(get_class($vehicle) . ' was created with id ' . $vehicle->id); }); $car = Car::create(); // Logs "Car was created with id 1" // Register an event on a child — does NOT affect parent or siblings Car::created(function ($car) { $car->driver_id = 99; }); $plane = Plane::create(); // $plane->driver_id is NOT set; the Car listener did not fire ``` ``` -------------------------------- ### Define Child Model with HasParent Trait Source: https://context7.com/tightenco/parental/llms.txt Add the `HasParent` trait to each child model. This trait ensures that table, foreign key, and joining table names are correctly resolved using the parent class name. It also registers a global scope to automatically filter queries by the model's type. ```php use Parental\HasParent; class Car extends Vehicle { use HasParent; // Child-specific relationships and methods public function passengers() { return $this->hasMany(Passenger::class, 'vehicle_id'); } public function startEngine(): string { return 'Vroom!'; } } class Plane extends Vehicle { use HasParent; public function altitude(): string { return 'Cruising at 35,000 ft'; } } // Queries "vehicles" table WHERE type = 'car' $car = Car::first(); echo $car->startEngine(); // "Vroom!" echo $car->getTable(); // "vehicles" (not "cars") // Foreign key is derived from parent class name echo (new Car)->getForeignKey(); // "vehicle_id" (not "car_id") ``` -------------------------------- ### Add 'type' Column for Child Model Access Source: https://github.com/tightenco/parental/blob/main/readme.md Modify the database schema to include a 'type' column, which is essential for Parental to differentiate between child models. ```php Schema::table('users', function ($table) { $table->string('type')->nullable(); }); ``` -------------------------------- ### Define Parent Model with HasChildren Trait Source: https://context7.com/tightenco/parental/llms.txt Add the `HasChildren` trait to the parent Eloquent model. This enables type-dispatching and event propagation to child models. Optionally, map short aliases to child classes using the `$childTypes` property. ```php use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; class Vehicle extends Model { use HasChildren; protected $fillable = ['type', 'driver_id']; // Optional: map short aliases to child classes protected $childTypes = [ 'car' => Car::class, 'plane' => Plane::class, 'train' => Train::class, ]; } // All three rows are written to the "vehicles" table $car = Car::create(['driver_id' => 1]); // type = 'car' $plane = Plane::create(['driver_id' => 2]); // type = 'plane' // Returns a collection of Car, Plane, and Train instances — not just Vehicle $vehicles = Vehicle::all(); // => Illuminate\Database\Eloquent\Collection [Car, Plane, Train, ...] ``` -------------------------------- ### Eager Load Child Model Relationship Counts from Collection Source: https://github.com/tightenco/parental/blob/main/readme.md Eager-load the count of relationships for child models within an Eloquent Collection using `loadChildrenCount`. This efficiently populates relationship counts for all applicable child models in the collection. ```php $messages = Message::all(); $messages->loadChildrenCount([ TextMessage::class => ['mentions'], ImageMessage::class => ['attachments'], ]); ``` -------------------------------- ### Set Custom Type Column Name Source: https://github.com/tightenco/parental/blob/main/readme.md Override the default 'type' column name by defining the `$childColumn` property on the parent model. ```php namespace App\Models; use Illuminate\Database\Eloquent\Model; use Parental\HasChildren; class User extends Model { use HasChildren; protected $fillable = ['parental_type']; protected $childColumn = 'parental_type'; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.