Питання на співбесіді з PHP Laravel 2026: Eloquent, Черги та Архітектурні патерни
Повний посібник з питань на співбесіді Laravel 2026. Eloquent ORM, система черг, архітектурні патерни та найкращі практики для PHP розробників.

Laravel залишається провідним PHP фреймворком для корпоративних веб-додатків у 2026 році. З виходом Laravel 12 та постійним розвитком екосистеми, питання на співбесідах стали більш вимогливими, охоплюючи просунуті концепції Eloquent ORM, системи черг та архітектурні патерни. Ця стаття розглядає ключові технічні теми, які часто зустрічаються на співбесідах на позиції Laravel Developer.
Остання версія Laravel використовує атрибути PHP 8.4 для визначення маршрутизації та middleware. Знання нового синтаксису наразі очікується на більшості співбесід, оскільки корпоративні проекти мігрують на найновіші версії фреймворку.
Eloquent ORM: Просунуті зв'язки та оптимізація запитів
Eloquent ORM є серцем Laravel, і питання щодо просунутих зв'язків та оптимізації N+1 з'являються практично на кожній співбесіді. Інтерв'юери очікують глибокого розуміння eager loading, lazy loading та технік оптимізації запитів.
Основне питання стосується різниці між with() та load(). Метод with() виконує eager loading на етапі побудови запиту, тоді як load() здійснює lazy eager loading на вже отриманій колекції моделей.
// Eager loading - один запит з JOIN
$posts = Post::with(["author", "comments.user"])->get();
// Lazy eager loading - завантаження після отримання
$posts = Post::all();
$posts->load("author");
// Constraining eager loads - фільтрація зв'язків
$users = User::with(["posts" => function ($query) {
$query->where("published", true)
->orderBy("created_at", "desc")
->limit(5);
}])->get();Просунуті питання охоплюють поліморфні зв'язки many-to-many та реалізацію власних типів зв'язків. Поліморфізм в Eloquent дозволяє гнучке моделювання даних, де одна модель може належати до різних типів моделей.
// Поліморфний зв'язок many-to-many
class Tag extends Model
{
public function posts(): MorphToMany
{
return $this->morphedByMany(Post::class, "taggable");
}
public function videos(): MorphToMany
{
return $this->morphedByMany(Video::class, "taggable");
}
}
class Post extends Model
{
public function tags(): MorphToMany
{
return $this->morphToMany(Tag::class, "taggable");
}
}Query Builder vs Raw SQL: Коли використовувати кожен підхід
Інтерв'юери часто запитують про сценарії, коли Query Builder недостатньо і необхідно використовувати сирий SQL. Знання методів DB::raw(), whereRaw() та selectRaw() є обов'язковим для розробників, які працюють зі складними аналітичними запитами.
// Складний аналітичний запит з віконними функціями
$salesRanking = DB::table("sales")
->select([
"product_id",
"total_amount",
DB::raw("RANK() OVER (PARTITION BY category_id ORDER BY total_amount DESC) as category_rank"),
DB::raw("SUM(total_amount) OVER (PARTITION BY category_id) as category_total")
])
->whereYear("created_at", 2026)
->get();
// Підзапит як джерело даних
$topSellers = DB::table(DB::raw("(
SELECT seller_id, SUM(amount) as total_sales
FROM orders
WHERE status = 'completed'
GROUP BY seller_id
HAVING SUM(amount) > 10000
) as top_sellers"))
->join("users", "users.id", "=", "top_sellers.seller_id")
->select("users.name", "top_sellers.total_sales")
->orderByDesc("total_sales")
->get();Система черг Laravel: Jobs, Workers та стратегії повторних спроб
Система черг є фундаментальним механізмом для масштабованих додатків Laravel. Питання на співбесідах зосереджуються на реалізації Job класів, конфігурації workers та стратегіях обробки помилок.
namespace App\Jobs;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Queue\Middleware\WithoutOverlapping;
class ProcessPayment implements ShouldQueue, ShouldBeUnique
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
public int $tries = 3;
public int $backoff = 60;
public int $timeout = 120;
public int $uniqueFor = 3600;
public function __construct(
private readonly Order $order,
private readonly string $paymentMethod
) {}
public function middleware(): array
{
return [
new WithoutOverlapping($this->order->id),
];
}
public function uniqueId(): string
{
return $this->order->id;
}
public function handle(PaymentGateway $gateway): void
{
$result = $gateway->charge(
$this->order->total,
$this->paymentMethod
);
if ($result->successful()) {
$this->order->markAsPaid();
}
}
public function failed(\Throwable $exception): void
{
Log::error("Payment failed", [
"order_id" => $this->order->id,
"error" => $exception->getMessage()
]);
$this->order->markAsPaymentFailed();
}
}Просунуті теми включають Job Batching, який дозволяє групувати кілька завдань та відстежувати їх прогрес як єдине ціле.
use Illuminate\Bus\Batch;
use Illuminate\Support\Facades\Bus;
$batch = Bus::batch([
new ProcessPodcast($podcast1),
new ProcessPodcast($podcast2),
new ProcessPodcast($podcast3),
])->then(function (Batch $batch) {
Log::info("All podcasts processed successfully");
})->catch(function (Batch $batch, \Throwable $e) {
Log::error("Batch processing failed", ["error" => $e->getMessage()]);
})->finally(function (Batch $batch) {
Cache::forget("processing_podcasts");
})->allowFailures()->dispatch();
// Відстеження прогресу
$progress = $batch->progress();
$pending = $batch->pendingJobs;
$failed = $batch->failedJobs;Архітектурні патерни: Repository, Service Layer та Action Classes
Питання про архітектуру додатків Laravel є стандартом на співбесідах на позиції mid та senior. Repository Pattern ізолює логіку доступу до даних, тоді як Service Layer інкапсулює бізнес-логіку.
// Repository Interface
namespace App\Repositories\Contracts;
interface UserRepositoryInterface
{
public function findById(int $id): ?User;
public function findByEmail(string $email): ?User;
public function create(array $data): User;
public function update(User $user, array $data): User;
public function delete(User $user): bool;
public function paginate(int $perPage = 15): LengthAwarePaginator;
}
// Repository Implementation
namespace App\Repositories;
class EloquentUserRepository implements UserRepositoryInterface
{
public function __construct(
private readonly User $model
) {}
public function findById(int $id): ?User
{
return $this->model->find($id);
}
public function findByEmail(string $email): ?User
{
return $this->model->where("email", $email)->first();
}
public function create(array $data): User
{
return $this->model->create($data);
}
public function paginate(int $perPage = 15): LengthAwarePaginator
{
return $this->model->latest()->paginate($perPage);
}
}Action Classes — це сучасний патерн, який просувається спільнотою Laravel, де кожен клас відповідає за одну бізнес-операцію.
namespace App\Actions;
class CreateUserAction
{
public function __construct(
private readonly UserRepositoryInterface $users,
private readonly HashManager $hash,
private readonly Dispatcher $events
) {}
public function execute(array $data): User
{
$user = $this->users->create([
"name" => $data["name"],
"email" => $data["email"],
"password" => $this->hash->make($data["password"]),
]);
$this->events->dispatch(new UserCreated($user));
return $user;
}
}
// Використання в контролері
class UserController extends Controller
{
public function store(
StoreUserRequest $request,
CreateUserAction $action
): JsonResponse {
$user = $action->execute($request->validated());
return response()->json($user, 201);
}
}Middleware та життєвий цикл запиту
Розуміння життєвого циклу HTTP запиту в Laravel є критично важливим. Інтерв'юери запитують про порядок виконання middleware, різницю між global та route middleware та реалізацію власних middleware.
namespace App\Http\Middleware;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
class EnsureUserIsSubscribed
{
public function handle(Request $request, Closure $next): Response
{
if (!$request->user()?->subscribed()) {
return redirect()->route("subscription.plans");
}
return $next($request);
}
}
// Terminable middleware - виконується після надсилання відповіді
class LogResponseTime
{
private float $startTime;
public function handle(Request $request, Closure $next): Response
{
$this->startTime = microtime(true);
return $next($request);
}
public function terminate(Request $request, Response $response): void
{
$duration = microtime(true) - $this->startTime;
Log::channel("performance")->info("Request completed", [
"path" => $request->path(),
"duration_ms" => round($duration * 1000, 2)
]);
}
}Тестування в Laravel: Feature та Unit Tests
Тестування є невід'ємною частиною технічних співбесід. Кандидати повинні знати різницю між Feature Tests та Unit Tests та вміти мокати залежності.
namespace Tests\Feature;
use App\Models\User;
use App\Models\Post;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;
class PostApiTest extends TestCase
{
use RefreshDatabase;
public function test_user_can_create_post(): void
{
$user = User::factory()->create();
$response = $this->actingAs($user)
->postJson("/api/posts", [
"title" => "Test Post",
"content" => "Test content"
]);
$response->assertStatus(201)
->assertJsonStructure([
"data" => ["id", "title", "content", "created_at"]
]);
$this->assertDatabaseHas("posts", [
"title" => "Test Post",
"user_id" => $user->id
]);
}
public function test_unauthenticated_user_cannot_create_post(): void
{
$response = $this->postJson("/api/posts", [
"title" => "Test Post"
]);
$response->assertStatus(401);
}
}Мокання зовнішніх сервісів за допомогою Facades:
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Queue;
public function test_payment_webhook_dispatches_job(): void
{
Queue::fake();
$response = $this->postJson("/webhooks/stripe", [
"type" => "payment_intent.succeeded",
"data" => ["object" => ["id" => "pi_123"]]
]);
$response->assertOk();
Queue::assertPushed(ProcessPaymentWebhook::class);
}
public function test_external_api_integration(): void
{
Http::fake([
"api.example.com/*" => Http::response(["status" => "ok"], 200)
]);
$service = app(ExternalApiService::class);
$result = $service->fetchData();
$this->assertEquals("ok", $result["status"]);
Http::assertSent(fn ($request) =>
$request->url() === "https://api.example.com/data"
);
}Готовий до співбесід з Laravel?
Практикуйся з нашими інтерактивними симуляторами, flashcards та технічними тестами.
Висновок
Співбесіди на позиції Laravel Developer у 2026 році вимагають ґрунтовного розуміння Eloquent ORM, системи черг та архітектурних патернів. Кандидати повинні знати просунуті техніки оптимізації запитів, реалізацію Job Batching та патерни Repository і Action Classes. Практичне знання тестування з використанням PHPUnit та мокання залежностей є додатковою перевагою під час процесу найму. Постійний розвиток фреймворку Laravel вимагає від розробників регулярного оновлення знань про найновіші функції та найкращі практики.
Чи знайдеш ти помилку в Laravel?
Справжній фрагмент коду, прихована помилка, одна спроба на день. Щоб спробувати, акаунт не потрібен.

Автор:
Anthony Fillion-MailletЗасновник SharpSkill
Fullstack-розробник понад 10 років. Керує SharpSkill і відповідає за все, що тут публікується.
Оновлено 16 вересня 2026 р.
Поділитися
Пов'язані статті

Laravel Octane у 2026: Swoole, RoadRunner та оптимізація продуктивності
Повний посібник з Laravel Octane у 2026 році. Порівняння Swoole та RoadRunner, техніки оптимізації продуктивності, конфігурація для продакшену та питання на співбесідах.

Питання на співбесіду PHP Laravel Developer 2026: Повний посібник з підготовки
Комплексний посібник з технічних питань на співбесіду для PHP Laravel розробників у 2026 році. Охоплює Eloquent ORM, Service Container, авторизацію, черги та тестування.

Рішення Laravel: Розширені Патерни, Налагодження та Питання на Співбесіді 2026
Комплексний посібник з розширених архітектурних патернів Laravel, технік налагодження з Telescope та найпоширеніших питань на співбесідах для розробників Laravel.