Junior: питання на співбесіді з теми «Eloquent»
Найпопулярніші питання з реальних Laravel/PHP співбесід для всіх рівнів
7 питань
Eloquent - це ORM (object-relational mapping) Laravel, реалізація патерну Active Record. Кожній таблиці відповідає модель (зазвичай у app/Models), рядок таблиці - це екземпляр моделі, а робота з даними виглядає як робота зі звичайними PHP-об'єктами замість написання SQL.
Створити модель (за конвенцією однина: Post → таблиця posts):
php artisan make:model Post -mf # одразу з міграцією та фабрикою
Базові операції (CRUD):
$post = Post::create(['title' => 'Привіт']); // create
$post = Post::find(1); // read
$post->update(['title' => 'Оновлено']); // update
$post->delete(); // delete
Post::where('is_published', true)->latest()->get();
Що дає Eloquent понад Query Builder:
- Зв'язки -
hasOne,hasMany,belongsTo,belongsToMany, поліморфні. - Аксесори/мутатори та касти атрибутів (наприклад, дати, enum, JSON).
- Події моделі та обзервери (
creating,saved,deleted). - Scopes для перевикористання умов запитів.
Eloquent побудований поверх Query Builder, тож ті самі методи (where, orderBy, join) доступні і на моделях.
Обидва методи виконують запит, але повертають різне:
get()повертає колекцію (Illuminate\Database\Eloquent\Collection) усіх відповідних моделей. Якщо нічого не знайдено - порожню колекцію, а неnull. Підходить, коли треба перебрати кілька записів.first()повертає одну першу модель абоnull, якщо нічого не знайдено. Підходить, коли очікуєш один запис.
$posts = Post::where('active', true)->get(); // Collection (0..N моделей)
$post = Post::where('slug', $slug)->first(); // Post|null
foreach ($posts as $post) { /* ... */ } // get() - ітеруємо
echo $post?->title; // first() - перевіряємо на null
Споріднені методи:
find($id)- пошук за первинним ключем.firstOrFail()/findOrFail()- якfirst()/find(), але кидаютьModelNotFoundException(HTTP 404), якщо запис відсутній.pluck('email')- колекція значень одного стовпця.value('email')- одне скалярне значення з першого рядка.
Підсумок: get() - багато рядків (колекція), first() - один рядок (модель або null).
Eloquent підтримує всі поширені типи зв'язків між таблицями, кожен оголошується методом на моделі:
- One To One -
hasOne/belongsTo. Приклад:User↔Profile. - One To Many -
hasMany/belongsTo. Приклад:Post→ багатоComment. - Many To Many -
belongsToManyчерез проміжну (pivot) таблицю. Приклад:User↔Role. - Has One/Many Through - доступ до віддаленого зв'язку через проміжну модель.
- Polymorphic -
morphTo/morphMany: модель належить кільком типам (наприклад,Commentможе належати іPost, іVideo).
Оголошення зв'язку:
class Post extends Model
{
public function comments(): HasMany
{
return $this->hasMany(Comment::class);
}
}
class Comment extends Model
{
public function post(): BelongsTo
{
return $this->belongsTo(Post::class);
}
}
Використання:
$post->comments; // колекція коментарів
$comment->post->title; // зворотний бік
Post::with('comments')->get(); // eager loading проти N+1
Завжди завантажуйте потрібні зв'язки через with(), щоб уникнути проблеми N+1.
Soft Deletes - «м'яке» видалення: запис не стирається фізично, а отримує мітку часу в колонці deleted_at. Такі записи автоматично виключаються з усіх запитів.
class Post extends Model
{
use SoftDeletes; // + $table->softDeletes() у міграції
}
$post->delete(); // ставить deleted_at
Post::withTrashed()->get(); // включно з видаленими
$post->restore(); // відновити
$post->forceDelete(); // видалити назавжди
Навіщо: можливість відновлення, аудит, збереження посилальної цілісності.
Вони перетворюють атрибути моделі «на льоту». У сучасному 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.
find($id)повертає модель за первинним ключем абоnull.findOrFail($id)повертає модель або кидаєModelNotFoundException, яку Laravel автоматично перетворює на HTTP 404.
$post = Post::find($id);
if (! $post) { abort(404); } // ручна перевірка
$post = Post::findOrFail($id); // те саме одним рядком
findOrFail робить контролери чистішими. Аналогічна пара для запитів - first() / firstOrFail().
Докладніше в документації: Eloquent: не знайдено / findOrFail
Це «upsert»-методи, що позбавляють від ручних перевірок «існує / не існує».
// знайти за email; якщо нема - створити з усіма атрибутами
User::firstOrCreate(
['email' => $email],
['name' => $name]
);
// знайти за email; оновити name; якщо нема - створити
User::updateOrCreate(
['email' => $email],
['name' => $name]
);
Перший масив - умови пошуку, другий - значення для створення/оновлення. Споріднений firstOrNew() повертає незбережений екземпляр.