Laravel: Отношения моделей один ко многим - hasMany, belongsTo

Связь One-to-Many в Laravel описывает отношение один ко многим между двумя таблицами в базе данных. Например, у каждого пользователя может быть много постов.

Для определения такой связи в моделях Laravel используется метод hasMany на родительской модели и метод belongsTo на дочерней модели.

Пример кода с опущенными параметрами

hasMany

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class);
    }
}

belongsTo

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class);
    }
}

В этом примере метод hasMany определен на модели User, который возвращает коллекцию всех постов пользователя. Метод belongsTo определен на модели Post, который возвращает пользователя, которому принадлежит пост.

Пример кода с явным указанием параметров

hasMany

public function posts()
{
    return $this->hasMany(
        Post::class,
        'user_id', // Внешний ключ в таблице постов
        'id' // Локальный ключ в таблице пользователей
    );
}

Здесь мы явно указываем параметры связи, передавая в hasMany следующие аргументы:

  1. Класс связанной модели Post::class.
  2. Внешний ключ в таблице постов, который связывает посты с пользователем, в данном случае user_id.
  3. Локальный ключ в таблице пользователей, который связывает пользователя с его постами, в данном случае id.

Таким образом, мы явно указываем Laravel, как связать таблицы users и posts с помощью внешнего и локального ключей, что может быть полезно в случае, если названия столбцов в таблицах отличаются от стандартных.

belongsTo

public function user()
{
    return $this->belongsTo(
        User::class,
        'user_id', // Внешний ключ в таблице постов
        'id' // Локальный ключ в таблице пользователей
    );
}

Здесь мы явно указываем параметры связи, передавая в belongsTo следующие аргументы:

  1. Класс связанной модели User::class.
  2. Внешний ключ в таблице постов, который связывает пост с пользователем, в данном случае user_id.
  3. Локальный ключ в таблице пользователей, который связывает пользователя с его постом, в данном случае id.

Таким образом, мы явно указываем Laravel, как связать таблицы users и posts с помощью внешнего и локального ключей, что может быть полезно в случае, если названия столбцов в таблицах отличаются от стандартных.

Применение в реалистичных задачах

$user = User::find(1);

foreach ($user->posts as $post) {
    echo $post->title;
}

В этом примере мы получаем пользователя с id = 1 и выводим заголовки всех его постов.

  • Для оптимизации запросов при использовании связей можно использовать метод with, чтобы загрузить связанные модели заранее и избежать N+1 проблемы:
$users = User::with('posts')->get();

foreach ($users as $user) {
    foreach ($user->posts as $post) {
        echo $post->title;
    }
}
  • Если вы работаете с большим количеством связанных моделей, рекомендуется использовать отложенную загрузку с помощью метода lazy:
$user = User::find(1);

$postCount = $user->posts()->count();

$posts = $user->posts()->lazy();

foreach ($posts as $post) {
    echo $post->title;
}
  • Для оптимизации производительности можно использовать кэширование связей, чтобы избежать повторных запросов к базе данных:
$user = User::find(1);

$posts = Cache::remember('user.posts.' . $user->id, now()->addHour(), function () use ($user) {
    return $user->posts;
});

foreach ($posts as $post) {
    echo $post->title;
}
  • Если вам нужно изменить поведение связи (например, добавить условие), вы можете использовать анонимную функцию в методе hasMany или belongsTo:
// Модель User

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
    public function publishedPosts()
    {
        return $this->hasMany(Post::class)->where('published', true);
    }
}

В этом примере мы определили новую связь publishedPosts, которая возвращает только опубликованные посты пользователя.

Вы можете использовать эту связь следующим образом:

$user = User::find(1);

foreach ($user->publishedPosts as $post) {
    echo $post->title;
}
  • Для оптимизации запросов при использовании анонимных функций с условиями, можно использовать метод with и передать анонимную функцию в качестве аргумента:
$users = User::with(['posts' => function ($query) {
    $query->where('published', true);
}])->get();

foreach ($users as $user) {
    foreach ($user->posts as $post) {
        echo $post->title;
    }
}
  • Если вам нужно работать с связями в массовом режиме, вы можете использовать метод create на связанной модели:
$user = User::find(1);

$user->posts()->create([
    'title' => 'Название поста',
    'content' => 'Текст поста',
    'published' => true,
]);

В этом примере мы создаем новый пост для пользователя с id = 1.

  • Используйте именованные маршруты для ссылок на связанные ресурсы в вашем приложении:
Route::get('/users/{user}/posts/{post}', function ($user, $post) {
    $post = Post::findOrFail($post);

    if ($post->user_id != $user) {
        abort(404);
    }

    return view('posts.show', compact('post'));
})->name('users.posts.show');

В этом примере мы создали именованный маршрут для просмотра конкретного поста пользователя. Мы используем user и post параметры в URL, чтобы определить пользователя и пост, а затем проверяем, что пост принадлежит указанному пользователю. Далее мы отображаем шаблон posts.show, передавая в него переменную $post.

В шаблоне можно использовать ссылку на маршрут, используя метод route:

<a href="{{ route('users.posts.show', ['user' => $post->user_id, 'post' => $post->id]) }}">
    {{ $post->title }}
</a>

В этом примере мы используем метод route для создания ссылки на маршрут users.posts.show, передавая в него параметры user и post.

Статьи по теме Laravel Relations

Комментарии (0)

  1. Напишите первый комментарий
*Комментарий будет опубликован после проверки модератором

Похожие статьи

Загрузка изображения в Laravel

Русификация Laravel

Добавить поле к существующей таблице Laravel

Как поменять язык в Faker

Транслитерация URL в Laravel. Примеры str_slug()

Разработка бота Telegram с помощью Botman на локальном компьютере

Валидация данных в Laravel form request

Laravel Excel - Базовый экспорт

Добавить в botman editMessageText для Telegram

Как сделать middleware в Laravel 6 - простой пример

Laravel: Отношения моделей многие ко многим - belongsToMany

Laravel: Отношения моделей один ко многим - hasMany, belongsTo

Как русифицировать или поменять шаблон уведомления о сбросе пароля в Laravel

Создать ссылку на storage из внешнего каталога для Laravel

Установить Laravel в отдельную папку (site.ru/laravel/)

Валидация номера кредитной карты на PHP (Laravel)

Создание form request в Laravel: руководство для начинающих

Связать папку storage с папкой public в Laravel

Экспорт маршрутов из Laravel в JSON файл

Откуда в Laravel Jetstream (inertia) prop auth.user?

Обработка ошибок в Laravel form request

Постраничная навигация на Bootstrap в Laravel 8

Blade - расширить @section с использованием директивы @parent

Добавить данные об авторизации при каждом запросе к API в Laravel

Работа с файлами в Laravel Form Request

Работа с вложенными объектами и коллекциями в Laravel form request

Laravel: Отношение через таблицу-посредника - hasOneThrough()

Стандартные свойства модели в Laravel

Laravel: Отношения моделей один к одному - hasOne, belongsTo

Laravel: Отношение через таблицу-посредника - hasManyThrough()

Авторизацией и аутентификация в Laravel form request

Установка Laravel и создание нового проекта

Создание уникального индекса в миграции Laravel

Laravel form request для создания API-запросов

Настройка команды CRON на хостинге nic.ru для активации Laravel schedule

HTTP-запросы в Laravel form request - работа с различными типами запросов

Создание класса модели в Laravel

Создание таблицы в базе данных (миграции) для модели в Laravel

Как создать модель в Laravel

Базовые методы CRUD контроллера для модели в Laravel

Наш сайт использует куки, нажмите «ОК» если вы не против
OK