Связь «Многие ко многим» (Many to many)

Создание таблиц

Сначала надо создать модели Post и Tag, а также таблицу «post_tag» (по названиям моделей в алфавитном порядке).

php artisan make:model Post -m
php artisan make:model Tag -m
php artisan make:migration create_post_tag_table --create=post_tag

В папке database/migrations/ будут созданы три файла, которые создадут таблицы в базе данных. В этих файлах надо прописать поля, которые надо создать в базе данных.

# database/migrations/{date}_create_posts_table.php
class CreatePostsTable extends Migration
{
    public function up()
    {
        Schema::create('posts', function(Blueprint $table){
            $table->increments('id');
            $table->string('title');
            $table->text('content');
            $table->timestamps();
        });
    }

    // …
}


# database/migrations/{date}_create_tags_table.php
class CreateTagsTable extends Migration
{
    public function up()
    {
        Schema::create('tags', function(Blueprint $table){
            $table->increments('id');
            $table->string('title');
            $table->timestamps();
        });
    }

    // …
}


# database/migrations/{date}_create_post_tag_table.php
class CreatePostTagTable extends Migration
{
    public function up()
    {
        Schema::create('post_tag', function(Blueprint $table){
            $table->increments('id');
            $table->integer('post_id')->unsigned();
            $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');

            $table->integer('tag_id')->unsigned();
            $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade');
        });
    }

    // …
}

И выполнить команду:

php artisan migrate

Для полей «post_id» и «tag_id» создаётся внешний ключ (foreign key). Он позволяет при удалении поста или тега автоматически удалять запись в таблице «post_tag».

Вывод тегов

В файле app/Post.php надо добавить следующий код:

// app/Post.php

class Post extends Model
{

    public function tags()
    {
        return $this->belongsToMany('App\Tag');
    }

}

Теперь можно выбирать теги:

# app/Http/Controllers/PostController.php

class PostController extends Controller
{
    public function index()
    {
        $tags = Post::find(1)->tags;
    }
}

Добавить и удалить тег

Добавить тег можно через метод attach().

# app/Http/Controllers/PostController.php

// добавить тег (по его ИД)
Post::find(1)->tags()->attach(3);

// добавить несколько тегов
Post::find(1)->tags()->attach([1,3]);

Если повторно выполнить метод attach(), то для поста добавится тотже тег.

Удалить тег можно через метод detach().

# app/Http/Controllers/PostController.php

// удалить указанный тег
Post::find(1)->tags()->detach(3);

// удалить несколько тегов
Post::find(1)->tags()->detach([1,3]);

// удалить все теги поста
Post::find(1)->tags()->detach();

Также есть методы sync() и syncWithoutDetaching(). Первая сохраняет указанные теги, удаляя лишние, а вторая работает также, только не удаляет уже существующие теги.

# app/Http/Controllers/PostController.php

// добавить указанные теги, удалив лишние
Post::find(1)->tags()->sync([1,3]);

// добавить указанные теги, не удаляя существующие
Post::find(1)->tags()->syncWithoutDetaching([1,3]);