Ответ
В Laravel Eloquent отношения определяются как методы в классе модели. Они строят SQL-запросы для связывания данных.
Основные типы отношений:
1. Один к одному (hasOne / belongsTo)
Предположим, у User есть один Phone.
// В модели User
public function phone() {
// User имеет один Phone. Второй аргумент — foreign key в таблице phones
return $this->hasOne(Phone::class, 'user_id');
}
// В модели Phone
public function user() {
// Phone принадлежит User. Второй аргумент — foreign key в таблице phones
return $this->belongsTo(User::class, 'user_id');
}
// Использование:
$phone = User::find(1)->phone; // Получить телефон пользователя
$user = $phone->user; // Получить владельца телефона
2. Один ко многим (hasMany / belongsTo)
У Post есть много Comment.
// В модели Post
public function comments() {
return $this->hasMany(Comment::class);
}
// В модели Comment
public function post() {
return $this->belongsTo(Post::class);
}
// Использование с жадной загрузкой (Eager Loading) для N+1 проблемы:
$posts = Post::with('comments')->get();
foreach ($posts as $post) {
foreach ($post->comments as $comment) { // Доп. запросов не будет
// ...
}
}
3. Многие ко многим (belongsToMany)
User может иметь много Role, и наоборот. Требуется промежуточная таблица (например, role_user).
// В модели User
public function roles() {
return $this->belongsToMany(Role::class); // Ищет таблицу 'role_user'
}
// Использование:
$user = User::find(1);
foreach ($user->roles as $role) {
echo $role->name;
}
// Присоединить роль к пользователю
$user->roles()->attach($roleId);
$user->roles()->sync([1, 2, 3]); // Синхронизировать список ролей
4. Полиморфные отношения
Позволяют модели принадлежать более чем одному типу модели. Например, Comment может принадлежать и Post, и Video.
// В модели Comment
public function commentable() {
return $this->morphTo();
}
// В моделях Post и Video
public function comments() {
return $this->morphMany(Comment::class, 'commentable');
}
// Использование:
$comment = Comment::find(1);
$commentable = $comment->commentable; // Получит либо Post, либо Video
Ключевые моменты:
- Имена методов — это соглашение, но можно переопределить имена таблиц и ключей.
- Всегда используйте жадную загрузку (
with()) при обращении к отношениям в циклах, чтобы избежать проблемы N+1 запроса. - Отношения — это построители запросов (Query Builders), к ним можно добавлять условия:
$user->posts()->where('active', 1)->get().