Какие типы связей между моделями поддерживает Eloquent ORM в Laravel?

«Какие типы связей между моделями поддерживает Eloquent ORM в Laravel?» — вопрос из категории Laravel, который задают на 24% собеседований PHP Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

В Laravel Eloquent я активно использую все типы связей для построения сложных моделей данных. Основные из них:

  1. Один к одному (One-to-One) Связь, где одна запись модели A относится к одной записи модели B. Например, у User есть один Profile.

    // В модели User
    public function profile()
    {
        return $this->hasOne(Profile::class);
    }
    // Использование: $user->profile->bio;
  2. Один ко многим (One-to-Many) Одна запись модели A имеет много записей модели B. Классический пример: у Post много Comment.

    // В модели Post
    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
    // Использование: $post->comments->each(...);
  3. Многие ко многим (Many-to-Many) Связь через промежуточную таблицу. Например, User может иметь много Role, и роль может быть у многих пользователей.

    // В модели User
    public function roles()
    {
        return $this->belongsToMany(Role::class);
    }
    // Eloquent автоматически использует таблицу `role_user`.
    // Получить всех пользователей роли: $role->users;
  4. Связь «Через» (Has Many Through) Позволяет получить доступ к удаленной связи через промежуточную модель. Например, в проекте у Country есть много User, а у каждого User много Post. Чтобы получить все посты страны:

    // В модели Country
    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
    // Eloquent выполнит JOIN через таблицу users.
  5. Полиморфные связи Позволяют модели принадлежать более чем одному типу другой модели на одной ассоциации. Использовал для реализации комментариев к разным сущностям (Post, Video).

    // Модель Comment
    public function commentable()
    {
        return $this->morphTo();
    }
    // Модель Post
    public function comments()
    {
        return $this->morphMany(Comment::class, 'commentable');
    }
    // Теперь можно получить $post->comments или $video->comments.

Ключевое преимущество Eloquent — декларативный синтаксис и «ленивая»/«жадная» загрузка (with()), которая позволяет оптимизировать запросы и избегать проблемы N+1.