Single Table Inheritance для Eloquent-моделей за допомогою Parental

0
Перекладено ШІ
Оригінал: Laravel News
Оновлено: 18 лютого, 2026
Parental — пакет для Laravel, що додає Single Table Inheritance у Eloquent і дозволяє зберігати різні підкласи в одній таблиці з колонкою типу. У статті показано, як налаштувати HasChildren/HasParent, кастомізувати колонку й аліаси типів, виконувати перехід між типами через become() та безпечно підвантажувати зв'язки, специфічні для кожного підкласу.

Parental — пакет для Laravel від Tighten, який додає Single Table Inheritance (STI) в Eloquent. Замість створення окремих таблиць для кожної варіації моделі, Parental дозволяє розширювати батьківську модель дочірніми класами, що використовують одну таблицю, де їх розрізняє колонка type.

# Сценарії використання

Single Table Inheritance корисний, коли моделі мають більшість спільних атрибутів, але відрізняються поведінкою. Типові приклади:

# Початок роботи

Встановіть пакет через Composer:

composer require tightenco/parental

Далі опишіть батьківську й дочірні моделі: додайте трейд HasChildren до батьківської моделі та HasParent до кожної дочірньої. Кожен дочірній клас наслідує батьківський і читає/записує дані в ту саму таблицю:

use Illuminate\Database\Eloquent\Model;
use Tighten\Parental\HasChildren;
 
class Order extends Model
{
    use HasChildren;
}
use Tighten\Parental\HasParent;
 
class PendingOrder extends Order
{
    use HasParent;
}
use Tighten\Parental\HasParent;
 
class ShippedOrder extends Order
{
    use HasParent;
}

Коли ви створюєте PendingOrder або ShippedOrder, запис зберігається в таблиці orders з колонкою type, яка ідентифікує дочірній клас.

# Власна колонка типу

Якщо в таблиці використовується інша назва колонки замість type, перевизначте її через властивість $childColumn у батьківській моделі:

class Order extends Model
{
    use HasChildren;
 
    protected $childColumn = 'status';
}

# Псевдоніми типів

За замовчуванням Parental зберігає повне ім'я класу в колонці type. Ви можете задати короткі псевдоніми через властивість $childTypes у батьківській моделі:

use Illuminate\Database\Eloquent\Model;
use Tighten\Parental\HasChildren;
 
class Order extends Model
{
    use HasChildren;
 
    protected $childTypes = [
        'pending' => PendingOrder::class,
        'shipped' => ShippedOrder::class,
    ];
}

У базі зберігатиметься pending або shipped замість повного імені класу. Колонка типу також підтримує цілі числа, якщо ви віддаєте перевагу числовим ідентифікаторам:

protected $childTypes = [
    1 => PendingOrder::class,
    2 => ShippedOrder::class,
];

# Перекласифікація через become()

Метод become() дозволяє динамічно змінити тип моделі на інший під час виконання. Наприклад, коли замовлення проходить життєвий цикл, його можна перекласифікувати в інший клас:

$order = PendingOrder::findOrFail(1);
 
$order = $order->become(ShippedOrder::class);
$order->save();

Виклик повертає новий екземпляр цільового класу з усіма початковими атрибутами. Parental також відправляє подію becoming перед переключенням — на неї можна підписатися, щоб реагувати на зміну типу й виконувати додаткову логіку.

# Попереднє завантаження відношень дочірніх класів

Коли запит повертає змішаний набір дочірніх типів, іноді потрібно підвантажити відношення, що існують лише в окремих класах. Виклик звичайного load() для відношення, визначеного лише в одному дочірньому класі, спричинить помилку. Parental має спеціальні хелпери, які звужують eager load до потрібного дочірнього класу:

$orders->loadChildren([
    PendingOrder::class => ['items'],
    ShippedOrder::class => ['shipments'],
]);

Ці хелпери працюють на Eloquent query builders, collections та paginators:

// On queries
Order::childrenWith([
    PendingOrder::class => ['items'],
    ShippedOrder::class => ['shipments'],
])->get();
 
// Count child-specific relationships
Order::childrenWithCount([
    PendingOrder::class => ['items'],
    ShippedOrder::class => ['shipments'],
])->get();

Щоб дізнатися більше про Parental і переглянути вихідний код, відвідайте GitHub repository.

Популярні

Logomark Logotype

Nuxt 3 + Laravel Sanctum: Просте та надійне рішення для автентифікації вашого SPA та API

У сучасній веб-розробці аутентифікація є ключовою для захисту додатків і даних користувачів. Дізнайтеся, як модуль nuxt-sanctum-authentication спростить інтеграцію між Nuxt 3 та Laravel Sanctum, забезпечуючи надійний і зручний спосіб реалізації аутентифікації для вашого проєкту

Logomark Logotype

Claude Agent тепер інтегрований в AI Assistant для PhpStorm

Ви коли-небудь задумувалися, як полегшити свою роботу в Laravel? У нашій статті ми розглядаємо, як інтеграція Claude Code в PhpStorm може підвищити вашу продуктивність, спростивши процес написання коду та навчання нових розробників. Читайте далі, щоб дізнатися більше про переваги та функціональність цього потужного поєднання

Logomark Logotype

Випущено Livewire 3.6

Laravel Livewire випустив нову версію 3.6, яка приносить з собою цікаві HTML-директиви для управління видимістю DOM-елементів і JavaScript-діями. Досліджуйте нові можливості Livewire, що допоможуть вам створити ще більш інтерактивні користувацькі інтерфейси!