DEV Community

Cynthia D
Cynthia D

Posted on

Laravel 9 Eloquent: Many-to-Many Relationships

Three hiccups I encountered while implementing this and how to solve it.

Cases

Case 1: "table not found" when trying to seed intermediate/pivot table:
Case 2: Migration fail for pivot table
Case 3: Find info on implementing 3-way pivot table in Laravel

Let's Solve It

Ok, so you figured out your tables have a many-to-many relationship and now you need to implement that in Laravel. In theory Laravel doesn’t need a model for the intermediate/pivot table, stating the many to many relationships in the parents models is enough.
But I encountered different situations where ultimately I found it easier or just necessary to create them.

By applying the Laravel naming conventions on your tables and models Laravel will automatically understand which table is the intermediate one given the correct relationship is stated in the models. The Laravel docs gives you clear indications on how to implement that.

Case 1 "table not found"

In my project I have a "users" and a "teas" table with an intermediate table "tea_user".
Naming conventions here being: use singular names of the parent tables in alphabetical order with underscore in between.

Case 1: Error "table not found" when trying to seed intermediate table:

The seeder will by default seek the plural naming of the model. Thus you get an error on running the seeding command telling you it does not exist even if the table name is correctly mentioned in the migration.

I found two easy solutions for that:

create a model for the intermediate table and add this line:
public $table = “name_table”;

class TeaUser extends Model
{
    use HasFactory;

    public $table = "tea_user";
}
Enter fullscreen mode Exit fullscreen mode

Or use the guidance from the Laravel docs for "customizing the name" but the shorter way like so:

class User extends Model
public function methodName()
    {
        return $this->belongsToMany(Name::class, 'tea_user');
    }
Enter fullscreen mode Exit fullscreen mode

Case 2 "Migration fail for pivot table"

Make sure you create your parent table migration before the intermediate otherwise you get a fail message when running the migration command. Because it doesn’t recognise the origin of the foreign keys.

Also the foreign key columns and the referencing columns should be of the same type.

For example the default type for id column is big integer so the foreign key should be ‘unsignedBigInteger’.

public function up()
    {
        Schema::create('tea_user', function (Blueprint $table) {
            $table->id();
            $table->unsignedBigInteger('user_id');
            $table->unsignedBigInteger('tea_id');
            $table->unsignedBigInteger('collection_id');
            $table->timestamps();
        });
    }
Enter fullscreen mode Exit fullscreen mode

Case 3 "implementing 3-way pivot table and work directly with it"

Create a model for it:

$ php artisan make:model  User -m
Enter fullscreen mode Exit fullscreen mode

And add the many-to-many relationships with each of the other parent tables in it:

class CollectionTeaUser extends Model
{
    use HasFactory;

    public function intermUsers()
    {
        return $this->belongsToMany(User::class, 'collection_tea_user');

    }

    public function intermTeas()
    {
        return $this->belongsToMany(Tea::class, 'collection_tea_user');

    }

    public function intermCollections()
    {
        return $this->belongsToMany(Collection::class, 'collection_tea_user');

    }

}
Enter fullscreen mode Exit fullscreen mode

I needed that for another part of my database that involved three parent tables all having a many-to-many relationship with each other.

This is the information I found while looking for a good setup for a 3-way intermediate table. For me the only resource I found that was clear and to the point about this subject so many thanks to Kaism!

Oh and keep reading the Laravel doc completely about the many-to-many relationships and you’ll discover good to know things like :

By default, only the model keys will be present on the pivot model. If your intermediate table contains extra attributes (columns), you must specify them when defining the relationship.

Also if you would like your intermediate table to have "created_at " and "updated_at" timestamps that are automatically maintained by Eloquent, call the "withTimestamps" method when defining the relationship.

return $this->belongsToMany(User::class, 'tea_user')
       ->withTimestamps();
Enter fullscreen mode Exit fullscreen mode

And don’t forget to create those columns then!

That’s it folks, good luck!

Top comments (0)