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

Laravel: архітектура застосунку

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

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

Дії й сервіси, контракти й фасади, об'єкти-значення через касти, стратегії через контейнер, власні драйвери, винятки домену, межі абстракцій - питання від middle до lead.

За спробу
20
У пулі
42
Проходжень
0
Середній бал
-
Пройшли на 70%+
-

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

25 питань

MVC (Model-View-Controller) - це архітектурний патерн, який розділяє застосунок на три шари, аби логіка обробки даних, бізнес-правила та відображення не змішувались між собою. Laravel побудований навколо MVC, тож кожному шару відповідає своя директорія.

Три складові:

  • Model - відповідає за дані та бізнес-логіку: спілкування з базою, зв'язки, валідаційні правила домену. У Laravel моделі розширюють Eloquent і лежать у app/Models.
  • View - відповідає лише за відображення. У Laravel це Blade-шаблони у resources/views; вони не повинні містити складної логіки.
  • Controller - приймає HTTP-запит, координує роботу моделей, готує дані й повертає View або відповідь. Лежать у app/Http/Controllers.

Як це працює разом: запит потрапляє на маршрут (routes/web.php), той викликає метод контролера. Контролер звертається до моделі за даними й передає їх у view:

class PostController extends Controller
{
    // Route Model Binding: $post резолвиться автоматично
    public function show(Post $post)
    {
        // контролер координує: бере дані з моделі й віддає у view
        return view('posts.show', ['post' => $post]);
    }
}

Навіщо: розділення відповідальностей спрощує тестування, підтримку й командну роботу - верстку можна змінити, не чіпаючи запити до БД, і навпаки. Laravel розширює класичний MVC сервісним контейнером, middleware та провайдерами.

Докладніше в документації: Архітектура та структура

  • CQRS (Command Query Responsibility Segregation) розділяє запис (Commands, що змінюють стан) і читання (Queries). Read-модель можна оптимізувати окремо (денормалізовані проєкції, окрема БД).
  • Event Sourcing зберігає не поточний стан, а послідовність подій; поточний стан відновлюється їх відтворенням. Дає повний аудит і «подорож у часі».
// концептуально
$aggregate->retrieve($uuid)
    ->placeOrder($data) // emit OrderPlaced
    ->persist(); // зберегти подію

У Laravel зазвичай через пакет spatie/laravel-event-sourcing (aggregates, projectors, reactors). Застосовувати варто там, де критичні аудит і складна доменна логіка - це додає суттєву складність, тож не для типового CRUD.

Шлях запиту:

  1. public/index.php - єдина точка входу; підключає автозавантажувач Composer.
  2. Створюється екземпляр застосунку (Service Container) із bootstrap/app.php.
  3. HTTP Kernel обробляє запит, завантажує Service Providers (register → boot).
  4. Запит проходить глобальні middleware (наприклад, обробка сесій, CSRF).
  5. Router зіставляє URL із маршрутом, виконуються middleware маршруту.
  6. Викликається контролер/замикання, формується Response.
  7. Відповідь проходить middleware у зворотному порядку й повертається клієнту; виконується terminate().

Ключова ідея: контейнер і провайдери бутстрапять застосунок, а middleware утворюють «цибулю» навколо обробки запиту.

Докладніше в документації: Життєвий цикл запиту

П'ять принципів ООП-дизайну. У Laravel вони реалізуються природно завдяки сервіс-контейнеру.

S - Single Responsibility: клас має одну причину для зміни. На практиці - виносити бізнес-логіку з «товстих» контролерів у Service/Action-класи, валідацію - у Form Requests, логіку життєвого циклу моделі - в Observers.

O - Open/Closed: відкритий для розширення, закритий для модифікації. Приклад - драйвери Laravel (cache, queue, filesystem): новий драйвер додається через extend(), не змінюючи ядро.

L - Liskov Substitution: реалізації взаємозамінні через спільний інтерфейс без поломки логіки - напр., будь-який драйвер кешу можна підставити замість іншого.

I - Interface Segregation: багато вузьких інтерфейсів краще за один «товстий»; клас не має реалізовувати методи, які не використовує.

D - Dependency Inversion: залежати від абстракцій, а не від реалізацій. Сервіс-контейнер - пряме втілення:

class OrderController
{
    public function __construct(private PaymentGateway $gateway) {} // інтерфейс
}

$this->app->bind(PaymentGateway::class, StripeGateway::class); // реалізація в провайдері

Користь: тестованість (легко підставити mock), гнучкість (зміна реалізації в одному місці). Водночас Senior знає, коли не переускладнювати - надмірна абстракція заради «чистоти» шкодить не менше за її відсутність.

DDD фокусується на моделюванні бізнес-домену спільною мовою з експертами. Ключові поняття: Entities, Value Objects, Aggregates, Domain Events, Bounded Contexts.

У Laravel це зазвичай означає відхід від стандартної структури (app/Models, app/Http) на користь організації за доменами:

app/Domain/Ordering/
    Models/Order.php
    Actions/PlaceOrder.php
    ValueObjects/Money.php
    Events/OrderPlaced.php
  • Бізнес-логіка живе в домені, а не в контролерах чи моделях-«божках».
  • Контролери стають тонкими адаптерами, що викликають доменні дії.

DDD виправданий у складних доменах; для CRUD він додає зайвий оверхед.

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

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