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

Laravel: Middle

20 питань · ~18 хв · Версія v3.0

Увійдіть, щоб продовжити

Service Container, черги, події, валідація, оптимізація.

За спробу
20
У пулі
100
Проходжень
73
Середній бал
84%
Пройшли на 70%+
86%

Питання для підготовки

147 питань

Service Container (IoC-контейнер) керує залежностями класів і виконує dependency injection. Він уміє автоматично будувати об'єкти, рекурсивно резолвлячи їхні залежності через type-hints конструктора.

// біндинг інтерфейсу до реалізації (зазвичай у Service Provider)
$this->app->bind(PaymentGateway::class, StripeGateway::class);

// тепер усюди, де просять PaymentGateway, прийде StripeGateway
public function __construct(private PaymentGateway $gateway) {}
  • bind() - нова реалізація щоразу.
  • singleton() - один екземпляр на весь життєвий цикл запиту.
  • app(PaymentGateway::class) - ручне резолвлення.

Це серце Laravel: контролери, middleware, події - усе резолвиться через контейнер.

Докладніше в документації: Service Container

Service Providers - центральне місце бутстрапу застосунку. Саме тут реєструються біндинги контейнера, слухачі подій, middleware, маршрути та публікація конфігів.

class AppServiceProvider extends ServiceProvider
{
    // лише біндинги в контейнер
    public function register(): void
    {
        $this->app->singleton(Parser::class);
    }

    // виконується після реєстрації всіх провайдерів
    public function boot(): void
    {
        Gate::define('admin', fn ($u) => $u->is_admin);
    }
}

Правило: у register() - лише біндинги (інші сервіси можуть бути ще не зареєстровані); у boot() - усе інше.

Докладніше в документації: Service Providers

N+1 виникає, коли ви завантажуєте N моделей одним запитом, а потім у циклі звертаєтесь до їхнього зв'язку - це генерує ще N запитів.

$posts = Post::all(); // 1 запит
foreach ($posts as $post) {
    echo $post->author->name; // +1 запит на кожен пост → N запитів
}

Рішення - eager loading через with():

$posts = Post::with('author')->get(); // лише 2 запити загалом

Вкладені та умовні зв'язки:

Post::with(['author', 'comments.user'])->get();        // вкладений eager
Post::with(['comments' => fn ($q) => $q->latest()])->get(); // умовний

Лічильники без завантаження зв'язку - withCount() (без N+1 і без вантаження самих рядків):

$posts = Post::withCount('comments')->get(); // доступ через $post->comments_count

Виявлення: Model::preventLazyLoading(! app()->isProduction()) у boot() кидає виняток на ледачих завантаженнях поза продакшеном; також допомагають Telescope і Debugbar.

Докладніше в документації: Eloquent: Eager Loading

Події дають слабке зв'язування: одна частина застосунку «оголошує», що щось сталося, інші - реагують, нічого не знаючи одна про одну.

event(new OrderShipped($order)); // диспатч

// слухач
class SendShipmentNotification
{
    public function handle(OrderShipped $event): void
    {
        // ...
    }
}
  • Слухача, що реалізує ShouldQueue, обробляють асинхронно в черзі.
  • У сучасному Laravel слухачі автоматично виявляються за type-hint у методі handle - ручна реєстрація не обов'язкова.

Приклад: подія UserRegistered → слухачі «надіслати лист», «нарахувати бонус», «оновити статистику».

Докладніше в документації: Events

Поліморфний зв'язок дозволяє моделі належати кільком різним типам моделей через один зв'язок.

class Comment extends Model
{
    public function commentable(): MorphTo
    {
        return $this->morphTo();
    }
}

class Post extends Model
{
    public function comments(): MorphMany
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
}

Таблиця comments має commentable_id + commentable_type. Тож Comment може належати і Post, і Video без окремих таблиць. Бувають також many-to-many поліморфні зв'язки (morphToMany), напр. теги.

Докладніше в документації: Поліморфні зв’язки

Прочитати - ще не значить знати

20 питань, по одному на екран, ~18 хв. Після завершення - розбір кожної помилки з посиланням на питання.