Many to Many (and Polymorphic)
Many-to-many relations are easy to make. Larawiz will automatically create pivot tables for your belongsToMany
and morphToMany
relations by using Laravel naming convention automatically.
Stranded in an ID-land
Many-to-many relations will not work if one of the parent models is:
- not using Primary Keys,
- using a custom Primary Key, or
- using a Primary Key different from the other parent models.
Larawiz will return an error and recite the Necronomicon loudly.
Many to Many
For many-to-many relations, just simply add the belongsToMany
in each. No need to add the Model pointing to the other if we can infer that from the relation names.
The pivot table is created automatically based on Laravel naming conventions, so you don't have to worry about doing it yourself manually.
models:
User:
name: string
roles: belongsToMany as:permissionsGroup
Role:
name: string
users: belongsToMany
2
3
4
5
6
7
8
class User extends Model
{
public function roles()
{
return $this->belongsToMany(Role::class)
->as('permissionsGroup');
}
}
class Role extends Model
{
public function users()
{
return $this->belongsToMany(User::class);
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Schema::create('users', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('roles', function (Blueprint $table) {
$table->id();
$table->string('name');
});
// Pivot created automatically for "Role" and "User".
Schema::create('role_user', function (Blueprint $table) {
$table->foreignIdFor(User::class);
$table->foreignIdFor(Role::class);
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Works even on one model
You don't need to declare both models with a belongsToMany
, automatic pivot table creation will work anyway.
Polymorphic Many to Many
For the case of many-to-many-polymorphic, Larawiz will also guess the pivot migration. Let's use the same Laravel example that many Posts or Videos having multiple Tags.
Note that, again, we didn't issue the pivot table anywhere.
I'm a wizard, not a mentalist
Polymorphic Many-to-many relations cannot be guessed by Larawiz. These needs both the target Model, and the name of ~able relation as second argument.
models:
Post:
name: string
tags: morphToMany:Tag,taggable
Video:
name: string
tags: morphToMany:Tag,taggable
Tag:
name: string
posts: morphedByMany:Post,taggable
videos: morphedByMany:Video,taggable
2
3
4
5
6
7
8
9
10
11
12
13
class Post extends Model
{
public function roles()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
class Video extends Model
{
public function users()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
class Tag extends Model
{
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable');
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('videos', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name');
});
// Polymorphic Pivot created automatically by Larawiz for "tags"
Schema::create('taggables', function (Blueprint $table) {
$table->foreignIdFor(Tag::class);
$table->morphs('taggable');
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
The example above will create the taggables
table automatically, since Larawiz uses the second argument from the morphToMany
.
Effortless relations
There is no need to create a morphedByMany
relation in the child model, but is recommended to.
If the models use UUID as primary key, no problem, Larawiz will automatically create a pivot table using uuidMorphs
and/or reference the target model by its primary key.
models:
Post:
id: uuid
name: string
tags: morphToMany:Tag,taggable
Video:
id: uuid
name: string
tags: morphToMany:Tag,taggable
Tag:
id: uuid
name: string
posts: morphedByMany:Post,taggable
videos: morphedByMany:Video,taggable
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Post extends Model
{
public function roles()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
class Video extends Model
{
public function users()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
class Tag extends Model
{
public function posts()
{
return $this->morphedByMany(Post::class, 'taggable');
}
public function videos()
{
return $this->morphedByMany(Video::class, 'taggable');
}
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// Polymorphic Pivot created automatically for [taggable].
Schema::create('taggables', function (Blueprint $table) {
$table->foreignIdFor(Tag::class);
$table->uuidMorphs('taggable');
});
2
3
4
5
Overriding automatic pivot tables
To override an automatic pivot table, you may create a migration for it. More details in the Migration section.