Как использовать отношение One-to-Many в Laravel

Источник: «How to Use a One-to-Many Relationship in Laravel?»
Отношения One-to-Many — это наиболее распространённый тип отношений, используемый в Laravel Eloquent и ORM в целом.

Отношения One-to-Many/Один-ко-Многим — это наиболее распространённый тип отношений, используемый в Laravel Eloquent и ORM в целом. В этом руководстве мы рассмотрим реализацию этих отношений, создав пример приложения с двумя Laravel Моделями: Автор и Книга. Отношения, которые мы установим между этими Моделями, диктуют, что автор может иметь несколько книг, связанных с ним, в то время как книга может иметь только одного автора.

В Laravel Eloquent отношение One-to-Many устанавливается с помощью метода hasMany в одном классе и соответствующего метода belongsTo в другом классе. Это создаст прямую связь между сущностями, обеспечивая лёгкий доступ к связанным данным.

Давайте сначала посмотрим на ERD ниже, где показаны две связанные таблицы, authors и books, которые мы свяжем через отношения Eloquent. Как вы можете видеть, книга имеет поле author_id, которое указывает на id её владельца в таблице authors.

ER-диаграмма, показывающая взаимосвязь между таблицами authors и books

Далее мы рассмотрим шаги по созданию необходимых миграций, определению отношений в моделях и выполнению общих операций над связанными данными. К концу этого руководства вы будете хорошо понимать, как использовать отношение One-to-Many

Шаг 1. Создание Миграций

Для начала давайте создадим миграции для таблиц authors и books. Выполните следующие команды в терминале:

php artisan make:migration create_authors_table --create=authors
php artisan make:migration create_books_table --create=books

Откройте файл миграции create_authors_table и добавьте следующий код:

database/migrations/2023_06_26_191132_create_authors_table.php:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/

public function up(): void
{
Schema::create('authors', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('email');
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/

public function down(): void
{
Schema::dropIfExists('authors');
}
};

Аналогично откройте файл миграции create_books_table и добавьте следующий код:

database/migrations/2023_06_26_191132_create_books_table.php:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
/**
* Run the migrations.
*/

public function up(): void
{
Schema::create('books', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description');
$table->foreignIdFor(\App\Models\Author::class)->constrained();
$table->timestamps();
});
}

/**
* Reverse the migrations.
*/

public function down(): void
{
Schema::dropIfExists('books');
}
};

В Laravel версии старше Laravel 8 вместо этого можно использовать следующее:

Schema::create('books', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('description');
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('authors');
$table->timestamps();
});

Для создания в базе данных таблиц authors и books выполните следующую команду artisan:

php artisan migrate

Шаг 2. Определение Моделей

Далее создадим модели для сущностей Author и Book. Выполните следующие команды:

php artisan make:model Author
php artisan make:model Book

Откройте модель Author и определите связь One-to-Many с моделью Book

app/Models/Author.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Author extends Model
{
public function books()
{
return $this->hasMany(Book::class);
}
}

Откройте модель Book и определите обратную связь One-to-Many:

app/Models/Book.php:

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
public function author()
{
return $this->belongsTo(Author::class);
}
}

Шаг 3. Выполнение Запросов

Теперь, когда мы настроили миграции и модели, давайте выполним несколько запросов для получения данных и манипулирования ими, используя отношения One-to-Many

routes/web.php:

use App\Models\Author;
use App\Models\Book;
use Illuminate\Support\Facades\Route;

Route::get('/hasmany', function () {
// Создаём автора
$author = new Author();
$author->name = 'John Doe';
$author->email = 'john@example.com';
$author->save();

// Создаём книги и ассоциируем с автором
$book1 = new Book();
$book1->title = 'Book 1';
$book1->description = 'Description for Book 1';
$author->books()->save($book1);

$book2 = new Book();
$book2->title = 'Book 2';
$book2->description = 'Description for Book 2';
$author->books()->save($book2);

// Получение книг определённого автора (через hasMany)
$author = Author::first();
$books = $author->books;
dump($books);

// Получение автора книга (через belongsTo)
$book = Book::first();
$author = $book->author;
dump($author);
});

Заключение

В этом руководстве мы рассмотрели, как использовать отношение One-to-Many в Laravel. Определив отношения, создав миграции, модели и выполнив запросы, мы успешно установили связь между двумя сущностями и эффективно извлекли связанные данные. Использование этих методов в ваших проектах поможет использовать возможности Eloquent и писать более лаконичный и читабельный код. Счастливого кодирования!

Дополнительные материалы

Предыдущая Статья

Готовимся к переходу на Symfony 6.4 и Symfony 7.0

Следующая Статья

Варианты использования Web Storage API в HTML