Laravel 11 прибрав з нового скелета `Http/Kernel`, `Console/Kernel`, `Exceptions/Handler`, половину конфігів і теку `lang`, перенісши налаштування в `bootstrap/app.php` і в дефолти фреймворка; 12 і 13 структуру не чіпали, тож оновлення між ними - це бамп версій у `composer.json` плюс вичитаний `UPGRADE.md`, а не переписування застосунку.
Laravel для Senior: питання на співбесіду
6 питань рівня Senior з теми Laravel з розгорнутими відповідями, порадами та перевіркою.
Вибір визначають три речі, а не смак: чи є другий клієнт (мобілка, партнери) — тоді API все одно доведеться зробити, і SPA стає майже безкоштовним; яка зернистість взаємодій — Livewire платить мережевим round-trip за кожен крок, тому годиться для форм, таблиць і фільтрів, а не для перетягування, канви чи офлайну; і хто це супроводжуватиме. Livewire тримає стан на сервері й ганяє снапшот компонента туди-сюди, SPA тримає стан у браузері й вимагає версіонованого контракту; Inertia — середина, де є клієнтські компоненти, але немає публічного API.
Octane тримає застосунок у памʼяті між запитами через Swoole, FrankenPHP або RoadRunner: бутстрап відбувається один раз, але стан більше не скидається сам.
Спершу розкласти час: браузерний waterfall відділяє TTFB від фронтенду, а далі Debugbar/Clockwork/Telescope локально й Blackfire або Pulse у проді показують, куди йдуть мілісекунди всередині PHP. Оптимізують за спаданням внеску: кількість запитів (N+1) → важкі запити з `EXPLAIN` → синхронні зовнішні виклики в чергу → гігієна деплою (`opcache`, `php artisan optimize`, `composer -o`), і лише потім кеш і Octane.
Стандартної структури вистачає, доки логіка сценарію вміщається в контролер плюс модель; далі вузьке місце — не назви тек, а те, що бізнес-правило не має одного власника. Дія з одним публічним методом і незмінним DTO на вході дає цього власника без DDD, а тактичні патерни DDD додають лише там, де є інваріанти, які треба захищати, і мова, якою говорить бізнес.
Колонка `tenant_id` дає спільні міграції та один пул зʼєднань, але ізоляція живе в кожному `WHERE`, і будь-який забутий фільтр стає витоком. База (або схема) на тенанта переносить межу на рівень конекшна ціною N міграцій, N бекапів і пулу зʼєднань. Глобальний scope закриває лише читання через Eloquent: `DB::table()`, правила `unique`/`exists` і відновлення моделі в черзі його не бачать, а кеш, файли, сесії та scheduler треба розводити по тенантах окремо.