Питання на співбесіді рівня Junior
Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів
40 питань
Soft Deletes - «м'яке» видалення: запис не стирається фізично, а отримує мітку часу в колонці deleted_at. Такі записи автоматично виключаються з усіх запитів.
class Post extends Model
{
use SoftDeletes; // + $table->softDeletes() у міграції
}
$post->delete(); // ставить deleted_at
Post::withTrashed()->get(); // включно з видаленими
$post->restore(); // відновити
$post->forceDelete(); // видалити назавжди
Навіщо: можливість відновлення, аудит, збереження посилальної цілісності.
Через об'єкт Request, який Laravel автоматично впроваджує в метод контролера:
public function store(Request $request)
{
$name = $request->input('name', 'default');
$email = $request->string('email'); // типізовані хелпери
$active = $request->boolean('active');
$all = $request->only(['name', 'email']);
}
Динамічний доступ $request->name теж працює, але його уникають через можливі колізії з параметрами маршруту. Для файлів - $request->file('avatar'), для перевірки наявності - $request->has('key').
Artisan - CLI Laravel. Він прискорює рутину: генерацію класів, міграції, очищення кешу, запуск черг тощо.
php artisan list # усі команди
php artisan make:model Post -mfsc # модель + міграція, фабрика, сидер, контролер
php artisan migrate
php artisan queue:work
php artisan tinker # інтерактивна REPL-консоль
Під капотом Artisan побудований на Symfony Console. Можна писати власні команди через make:command.
Сесії зберігають стан користувача між запитами. Laravel дає єдиний API поверх різних драйверів (file, cookie, database, redis), що налаштовуються в config/session.php.
session(['cart_id' => 42]); // записати
$id = session('cart_id'); // прочитати
$request->session()->forget('cart_id'); // видалити
session()->flush(); // очистити все
Для продакшену з кількома серверами зазвичай обирають redis або database, щоб сесія була спільною між інстансами.
Flash Data - дані, що живуть у сесії лише до наступного запиту й потім автоматично видаляються. Класичне застосування - повідомлення про результат дії після редиректу.
return redirect('/dashboard')->with('status', 'Профіль оновлено!');
@if (session('status'))
<div class="alert">{{ session('status') }}</div>
@endif
Під капотом - session()->flash('key', $value). Метод reflash() продовжує життя flash-даних ще на один запит.
У сучасному Laravel ассети збирає Vite. У шаблоні підключають директивою @vite:
@vite(['resources/css/app.css', 'resources/js/app.js'])
Під час розробки (npm run dev) Vite віддає файли з hot-reload; на продакшені (npm run build) - зібрані файли з хешами в імені для cache busting.
Для статичних файлів із public/ використовують хелпер asset('images/logo.png').
Вони перетворюють атрибути моделі «на льоту». У сучасному Laravel обидва описуються одним методом, що повертає Attribute:
protected function name(): Attribute
{
return Attribute::make(
get: fn (string $value) => ucfirst($value), // accessor (читання)
set: fn (string $value) => strtolower($value), // mutator (запис)
);
}
- Accessor форматує значення при отриманні (
$user->name). - Mutator форматує значення перед збереженням у БД.
Корисно для форматування, нормалізації або роботи з Value Objects.
Достатньо викликати paginate() замість get() - Laravel сам читає номер сторінки з query-параметра ?page=:
$posts = Post::latest()->paginate(15);
@foreach ($posts as $post) ... @endforeach
{{ $posts->links() }} {{-- кнопки навігації --}}
paginate()рахує загальну кількість (показує «сторінка X з Y»).simplePaginate()- лише «вперед/назад», безCOUNT(*), швидше на великих таблицях.cursorPaginate()- курсорна пагінація, найефективніша для нескінченного скролу.
Route Model Binding автоматично резолвить параметр маршруту в екземпляр моделі - не треба вручну робити findOrFail().
Route::get('/posts/{post}', [PostController::class, 'show']);
// $post - вже знайдена модель
public function show(Post $post)
{
return view('posts.show', compact('post'));
}
За замовчуванням пошук іде за id. Прив'язати за іншим стовпцем: {post:slug}. Якщо запис не знайдено - автоматично 404.
Згенерувати клас і описати логіку в handle():
php artisan make:command SendReports
class SendReports extends Command
{
protected $signature = 'reports:send {--month=}';
protected $description = 'Розіслати місячні звіти';
public function handle(): int
{
$this->info('Відправка...');
return self::SUCCESS;
}
}
Аргументи й опції описуються в $signature. Команду можна запускати вручну або ставити в розклад через Schedule::command('reports:send')->monthly().
Factory (фабрика) генерує фейкові дані моделей через Faker. Незамінна в тестах і сидерах.
class PostFactory extends Factory
{
public function definition(): array
{
return [
'title' => fake()->sentence(),
'body' => fake()->paragraphs(3, true),
];
}
}
Post::factory()->count(10)->create(); // 10 записів у БД
Post::factory()->published()->make(); // стан + без збереження
«Стани» (states) дозволяють описати варіації, наприклад ->published() чи ->trashed().
Локалізація дає багатомовність. Рядки перекладів лежать у lang/{locale} (наприклад, lang/uk/messages.php або JSON-файли).
// lang/uk/messages.php
return ['welcome' => 'Ласкаво просимо, :name'];
{{ __('messages.welcome', ['name' => $user->name]) }}
app()->setLocale('uk')перемикає мову (зазвичай у middleware).trans_choice()обирає форму за кількістю (1 яблуко / 2 яблука / 5 яблук).
Collection - обгортка над масивом із плавним, ланцюжковим API. Eloquent-запити повертають саме колекції.
$names = collect($users)
->filter(fn ($u) => $u->active)
->sortBy('name')
->map(fn ($u) => $u->name)
->values();
Десятки методів: map, filter, reduce, groupBy, pluck, each, sum. Код читається зрозуміліше за вкладені цикли й array_*-функції. Для дуже великих наборів є LazyCollection (на генераторах).
Лист описується класом Mailable, шаблон - Blade або Markdown.
php artisan make:mail WelcomeEmail --markdown=emails.welcome
Mail::to($user)->send(new WelcomeEmail($user));
Налаштування транспорту (SMTP, Mailgun, SES, log) - у config/mail.php та .env. Реалізувавши ShouldQueue на Mailable, відправку можна винести в чергу, щоб не блокувати запит.
Query Builder - плавний інтерфейс для побудови SQL-запитів без написання рядкового SQL. Працює з усіма підтримуваними СУБД і захищає від SQL-ін'єкцій через підготовлені вирази.
$users = DB::table('users')
->where('votes', '>', 100)
->orderBy('name')
->limit(10)
->get();
Повертає прості об'єкти stdClass. Eloquent побудований поверх Query Builder, тож ті самі методи (where, join, orderBy) доступні і на моделях.