Laravel 9 Eloquent: Many-to-Many Relationships
Published: 2022-06-17 09:44:52

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

## Cases

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

## Let's Solve It

Ok, so you figured out your tables have a [many-to-many relationship](https://laravel.com/docs/9.x/eloquent-relationships#many-to-many) 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](https://webdevetc.com/blog/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”;
```php
class TeaUser extends Model
{
    use HasFactory;
 
    public $table = "tea_user";
}
```

Or use the guidance from the Laravel docs for "customizing the name" but the shorter way like so:
```php
class User extends Model
public function methodName()
    {
        return $this->belongsToMany(Name::class, 'tea_user');
    }
 ```

## 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’.
```php
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();
        });
    }
```
## Case 3 "implementing 3-way pivot table and work directly with it"


Create a model for it:
```php
$ php artisan make:model  User -m
```

And add the many-to-many relationships with each of the other parent tables in it:
```php
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');

    }

}
```
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](https://medium.com/@kaism/3-way-pivot-table-in-laravel-d42d60462b06). 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](https://laravel.com/docs/9.x/eloquent-relationships#many-to-many) 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.
```php
return $this->belongsToMany(User::class, 'tea_user')
       ->withTimestamps();
```
And don’t forget to create those columns then!

That’s it folks, good luck!