Как создать запись в БД с отношением Many-to-many в Laravel?

Есть модель Post и в ней создаю отношения многие ко многим с таблицей жанров

class Post extends Model
{
    use HasFactory;

    protected $guarded = false;

    public function genres(): BelongsToMany
    {
        return $this->belongsToMany(Genres::class);
    }
}

Делаю пост запрос к методу store контроллера PostContoller и валидацию входных данных StoreRequest

public function store(StoreRequest $request)
{
    $data = $request->validated();

    $post = Post::create($data);

    return PostResource::make($post)->resolve();
}

Миграции таблиц posts|genres|genre_post выглядят примерно следующим образом posts

Schema::create('posts', function (Blueprint $table) {
    $table->id();

    $table->string('alias')->nullable()->unique();

    $table->string('title', 512)->nullable();
    $table->year('year')->nullable();
    $table->text('description')->nullable();

    $table->timestamps();
});

genres

Schema::create('genres', function (Blueprint $table) {
    $table->tinyIncrements('id');
    $table->string('name');
});

genre_post

Schema::create('genre_post', function (Blueprint $table) {

    $table->unsignedBigInteger('post_id')->nullable();
    $table->foreign('post_id')->references('id')->on('posts')->onDelete('cascade');

    $table->unsignedTinyInteger('genre_id')->nullable();
    $table->foreign('genre_id')->references('id')->on('genres')->onDelete('cascade');

});

При попытке создания записи выдаёт ошибку SQLSTATE[42S22]: Column not found: 1054 Unknown column 'genres' in 'field list'

Я понимаю, что в таблице posts у меня нет поля genres, но как сделать, что бы после валидации полей, просто отправить дату на создание поста подобным образом Post::create($data)? Можно ли вообще так и как это реализовать с отношениями?

А то совсем не хочется писать портянку по типу (да и думаю это не правильно):

if ($title = $request->has('title')) {
    // ...
}
if ($genres = $request->has('genres')) {
    foreach(explode(',', $genres) as $genre) {
        $this->post->genres()->attach($genre, [
            'post_id' => $post_id,
            'genre_id' => $genre
        ]);
    }
}

Ответы (1 шт):

Автор решения: Raz Galstyan

Вы должны написать BelongsToMany так.

public function genres(): BelongsToMany
{
    return $this->belongsToMany(Genres::class, 'genre_posts', 'post_id', 'genre_id');
}

И второй момент. Имя таблицы не правильно что бы было genre_post, надо дать имя в множественном числе genre_posts.

После того вы можете сделать attach таким образом.

$this->post->genres()->attach($genreIds);

Где $genreIds это array всех id которые нужно залить в базу.

→ Ссылка