Увійти Реєстрація
Блог Серії
Кар'єра
Вакансії Компанії
Навчання
Документація Співбесіди Тестування Відео
Екосистема
Пакети Ресурси Проєкти Інструменти Події
Інше
Про нас Реклама

Питання на співбесіді: Eloquent

Питання з реальних співбесід з відповідями: Laravel і PHP, бази даних, JavaScript і фронтенд, Git, Docker, API, безпека й архітектура. Тими самими темами, що й тести.

31 питань

Традиційно модель налаштовують захищеними властивостями й методами booted(). Laravel поступово додає PHP-атрибути класу, що описують ту саму конфігурацію декларативно:

use Illuminate\Database\Eloquent\Attributes\{Table, Fillable, Hidden, ObservedBy, ScopedBy, UseFactory, CollectedBy};

#[Table('legacy_orders', key: 'order_id', timestamps: false)]
#[Fillable(['customer_id', 'total', 'status'])]
#[Hidden(['internal_note'])]
#[ObservedBy(OrderObserver::class)]
#[ScopedBy(TenantScope::class)]
#[UseFactory(OrderFactory::class)]
#[CollectedBy(OrderCollection::class)]
final class Order extends Model {}

Те саме через властивості й методи:

class Order extends Model
{
    protected $table = 'legacy_orders';
    protected $primaryKey = 'order_id';
    public $timestamps = false;
    protected $fillable = ['customer_id', 'total', 'status'];
    protected $hidden = ['internal_note'];

    protected static function booted(): void
    {
        static::observe(OrderObserver::class);
        static::addGlobalScope(new TenantScope);
    }
}

Що дають атрибути:

  • конфігурація відокремлена від поведінки: метадані над класом, а в тілі лишаються зв'язки, касти, бізнес-методи;
  • видно одразу, які спостерігачі й глобальні області видимості підключені до моделі - не треба шукати по booted() і сервіс-провайдерах;
  • немає побічних ефектів у booted() і ризику забути parent::booted() у спадкоємцях;
  • статичний аналіз: IDE й інструменти читають атрибути через Reflection без запуску коду.

Що варто знати:

  • атрибути читаються через Reflection при першому зверненні й кешуються - на швидкість це практично не впливає;
  • успадкування: сам PHP атрибути не наслідує, але Eloquent шукає атрибут у класі моделі, її трейтах і далі в батьківських класах - тож конфігурація з базової моделі чи трейту діє в спадкоємцях, а найближчий атрибут перекриває дальші;
  • змішування стилів в одному проєкті (частина моделей з властивостями, частина з атрибутами) ускладнює читання - варто домовитися про один стиль;
  • не все має атрибут: касти, зв'язки, аксесори лишаються методами.

Інші атрибути Laravel у тому самому стилі: #[UsePolicy] для зв'язку моделі з політикою, #[UseResource] для API Resource, #[Scope] для позначення методу локальною областю видимості без префікса scope.

Практично: для нових моделей атрибути зручніші; переписувати старі заради стилю немає сенсу - поведінка однакова.

Докладніше в документації: Eloquent: назви таблиць