calebporzio/parental
Single-table inheritance for Laravel Eloquent. Store multiple model “types” in one table and let Parental automatically instantiate the right child class. Keeps polymorphic-like behavior simple, with familiar relationships, queries, and mass assignment.
composer require tightenco/parental (note: tightenco, not tighten in the package name).Parental trait to your parent model (e.g., Document), which must extend Illuminate\Database\Eloquent\Model.Invoice extends Document). No extra traits needed.type column exists in the shared table (default column name; configure via $childTypeColumn if needed).Document::all() automatically hydrates rows as Invoice, Receipt, etc., based on the type column — no manual casting.✅ Key insight: You don’t instantiate child models directly for persistence; the parent model’s
Parentaltrait intercepts query construction and model resolution automatically.
$childTypeAliases to store compact DB values ('inv' instead of 'Invoice'), especially when DB values must be stable across refactors.
class Document extends Model
{
use Parental;
protected $childTypeAliases = ['Invoice' => 'inv', 'Receipt' => 'rcpt'];
}
become(Child::class) to permanently convert a record to another type (updates DB and returns new instance).withChildType('relationship') and hasChildType('relationship') to load/filter only relationships that exist on specific child types.childType() to derive the type from complex conditions (e.g., status-based fallback).type column with cast(['type' => DocumentType::class]) — ensure enum cases match stored values or aliases.💡 Pro tip: Define child models empty by default — they inherit all relationships, accessors, and logic from the parent. Only override what differs.
->toJson() on collections containing multiple child types.fillable isn’t auto-merged in old versions: Ensure composer.lock has ≥ v1.3.6; otherwise, fillable arrays don’t combine across inheritance layers.Document::created(...)), wrap event registration in whenBooted() (see v1.6.0 changelog).type DB value doesn’t match child class name or alias — debug with Document::classToAlias(Invoice::class).childTypeColumn in the parent model and ensure Nova resources reference child models explicitly.::first() vs ::get(): first() returns the first row as its concrete type; get() returns a collection of correct child types. Don’t assume type homogeneity.ParentalServiceProvider is registered manually in bootstrap/app.php.How can I help you explore Laravel packages today?