Expressive: як використовувати Typed Objects для моделей Eloquent

Перекладено ШІ 0 Laravel News 30 травня, 2026

Пакет Laravel Expressive забезпечує сувору типізацію у вашому проєкті, перетворюючи моделі Eloquent на легковажні PHP-об'єкти. Дізнайтеся, як цей інструмент допоможе відокремити бізнес-логіку від бази даних без втрати гнучкості фреймворку.

Expressive від Wendell Adriel перетворює моделі Eloquent на типізовані PHP-об’єкти та дозволяє конвертувати їх назад для збереження даних. Мета інструменту — забезпечити чіткі межі типів для сервісів, екшенів та тестів, водночас залишаючи за Eloquent роботу із запитами, зв’язками, кастингом, правилами видимості та записом у базу.

Замість передачі важких моделей Eloquent через усю кодову базу, ви працюєте з легкими об’єктами з публічними властивостями. Це дозволяє відокремити бізнес-логіку від шару бази даних, не відмовляючись від функціоналу Eloquent.

# Підключення до моделей

Для активації функціоналу в моделях використовується trait IsExpressive. Атрибути #[Fillable] та #[Hidden] визначають, як модель відображатиметься у типізованому об’єкті:

use Illuminate\Database\Eloquent\Attributes\Fillable;
use Illuminate\Database\Eloquent\Attributes\Hidden;
use Illuminate\Database\Eloquent\Casts\Attribute;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\Relations\HasOne;
use Illuminate\Foundation\Auth\User as Authenticatable;
use WendellAdriel\Expressive\Concerns\IsExpressive;
 
#[Fillable(['name', 'email', 'role', 'password'])]
#[Hidden(['password', 'remember_token'])]
class User extends Authenticatable
{
    use IsExpressive;
 
    public function posts(): HasMany
    {
        return $this->hasMany(Post::class);
    }
 
    public function address(): HasOne
    {
        return $this->hasOne(Address::class);
    }
 
    protected function displayName(): Attribute
    {
        return Attribute::make(
            get: fn (): string => "{$this->name} ({$this->role->value})",
        );
    }
}

# Генерація класів Expressive

Пакет містить команду Artisan для швидкого створення типізованого класу на основі моделі:

php artisan make:expressive User --model="App\Models\User"

За замовчуванням згенеровані класи зберігаються в App\Expressive. Кожен клас розширює базовий Expressive і містить типізовані властивості, що відповідають колонкам бази, зв’язкам та аксесорам моделі:

use App\Enums\UserRole;
use App\Expressive\Address;
use App\Expressive\Post;
use Carbon\CarbonInterface;
use Illuminate\Support\Collection;
use WendellAdriel\Expressive\Attributes\Relationship;
use WendellAdriel\Expressive\Attributes\Virtual;
use WendellAdriel\Expressive\Expressive;
 
final class User extends Expressive
{
    public ?int $id = null;
 
    public string $name;
 
    public string $email;
 
    public UserRole $role;
 
    public ?CarbonInterface $createdAt = null;
 
    #[Relationship]
    public ?Address $address = null;
 
    /** @var Collection<int, Post>|null */
    #[Relationship]
    public ?Collection $posts = null;
 
    #[Virtual]
    public ?string $displayName = null;
}

Атрибут #[Relationship] позначає властивості для зв’язків Eloquent, а #[Virtual] — віртуальні значення (наприклад, displayName), яких немає в таблиці бази даних.

# Конвертація моделей у типізовані об'єкти

Метод expressive() можна викликати для моделі, колекції або Query Builder. Ви також можете вибірково додавати аксесори та зв’язки:

// Окремо взята модель із віртуальним атрибутом
$user = User::findOrFail(1)->expressive(attributes: ['display_name']);
 
// Колекція із завантаженими зв’язками
$users = User::query()->get()->expressive(relationships: ['posts']);
 
// Прямо через Query Builder
$users = User::query()
    ->where('active', true)
    ->expressive(relationships: ['posts']);

Зв’язки конвертуються рекурсивно: HasOne стає об’єктом Expressive, а HasMany — колекцією об’єктів Collection.

# Збереження типізованих об'єктів

Процес працює і у зворотному напрямку. Метод model() створює незбережений екземпляр Eloquent, а save() — записує дані в базу:

// Створення моделі в пам’яті без запису в БД
$model = (new App\Expressive\User([
    'name' => 'Wendell',
    'email' => 'wendell@example.com',
]))->model();
 
// Збереження моделі та її основних зв’язків
$saved = (new App\Expressive\User([
    'name' => 'Wendell',
    'email' => 'wendell@example.com',
]))->save();

Метод save() підтримує збереження кореневої моделі разом із прямими зв’язками, як-от BelongsTo, HasOne, HasMany, MorphOne та MorphMany. Обидва методи враховують правила масового заповнення (mass-assignment) та ігнорують не дозволені для заповнення атрибути.

# Встановлення

Встановити пакет можна через Composer:

composer require wendelladriel/laravel-expressive

Після цього опублікуйте файл конфігурації:

php artisan vendor:publish --tag="expressive"

Пакет потребує PHP 8.3 або новішої версії та підтримує Laravel 12 і 13. Більше деталей доступно в документації або в репозиторії на GitHub.

Популярні

Інше, що варто прочитати

14 Оновлено 01 червня, 2026

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

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

17 Оновлено 01 червня, 2026

Налаштування Xdebug з Docker та PHP 8.4 всього за одну хвилину

Встановлення Xdebug може бути складним завданням, але в цій статті ми розкриємо, як швидко та просто налаштувати його за допомогою Docker на прикладі Laravel. Дочитайте до кінця, щоб дізнатися, як за кілька хвилин зробити Xdebug вашим надійним помічником у розробці

53 Оновлено 01 червня, 2026

Усе, що нам відомо про Livewire 4

Нова версія Livewire 4, представленої Келебом Порзіо на Laracon US 2025, обіцяє значні покращення у швидкості та організації компонентів. Які з інноваційних функцій підкорять ваше серце? Читайте далі, щоб дізнатися більше про те, як Livewire 4 полегшить вашу роботу