Laravel ManyToMany relationship Is reversing tables names

402 Views Asked by At

i need to make the post accepts as many language as i need so i have tow models post and language in post model:

public function languages(){
    return $this->belongsToMany(\App\Models\Language::class);
}

in my language model :

public function posts()
{
    return $this->belongsToMany(\App\Models\Post::class);
}

post migration :

  Schema::create('posts', function (Blueprint $table) {
        $table->id();
        $table->string('title');
        $table->text('body');
        $table->boolean('puplished')->default(false);
        $table->bigInteger('user_id')->unsigned();
        $table->foreign('user_id')->references('id')->on('users');
        $table->timestamps();
    });

language migration :

Schema::create('languages', function (Blueprint $table) {
        $table->id();
        $table->string('text')->unique();
        $table->string('value');
        $table->timestamps();
    });

i also created post_language_table migration to connect post and language:

Schema::create('post_language', function (Blueprint $table) {
        $table->id();
        $table->unsignedInteger('post_id');
        $table->unsignedInteger('language_id');
        $table->timestamps();
    });

in my controller :

$langs = collect(json_decode($request->languages,true))->pluck('id');
    $post = [];
    $post['body'] = $request->body;
    $post['title'] = $request->title;
    $post['user_id'] = 1;
    $new_post = \App\Models\Post::create($post);
    $new_post->languages()->attach($langs);

but when i try to insert new record to tha database this error shows:

Illuminate\Database\QueryException
SQLSTATE[42S02]: Base table or view not found: 1146 Table 'laravel.language_post' doesn't exist (SQL: 
insert into `language_post` (`language_id`, `post_id`) values (1, 4), (3, 4), (4, 4))

so the problem is that for some reason the table name is exchanged !

1

There are 1 best solutions below

1
On BEST ANSWER

The Laravel convention for pivot tables based on models is table1_table2, where table1 is the lowercase, singular version of the model that comes first in the alphabet, and table2 is the lowercase, singular version of the model that comes last in the alphabet. So in your case, the pivot table should be language_post, since L comes before P.

You can modify the pivot table in your migration:

Schema::create('language_post', ...)

Or override it on the relationship:

Post.php:

public function languages() {
  return $this->belongsToMany(Language::class, 'post_language');
}

Language.php

public function posts() {
  return $this->belongsToMany(Post::class, 'post_language');
}

The 2nd param passed to belongsToMany is the name of the pivot table.

From the documentation:

To determine the table name of the relationship's intermediate table, Eloquent will join the two related model names in alphabetical order.

https://laravel.com/docs/8.x/eloquent-relationships#many-to-many