Pivots Models
Intermediate table models, also called Pivot Models, are easy to do: simply point them out in the relations and Larawiz will automatically change the model type to a Pivot Model or Polymorphic Pivot Model, and add the corresponding migration.
Finish that spell
Always point the Pivot Model on all relations. If one relation is missing the pivot model, Larawiz will understand you will be using automatic pivot tables for that relation, and you will end up with an additional table.
Many-to-Many Pivot Models
If you want to use a Pivot Model, simply create a belongsToMany
and add the pivot model in ALL the relations as second parameter, or through using
.
models:
User:
name: string
subscriptions: belongsToMany:Podcast using:Subscription
Podcast:
title: string
subscribers: belongsToMany:User,Subscription # Same effect
Subscription:
user: belongsTo
podcast: belongsTo
last_heard: timestamp nullable
2
3
4
5
6
7
8
9
10
11
12
13
class User extends Model
{
public function subscriptions()
{
return $this->belongsToMany(Podcast::class, Subscription::class);
}
}
class Podcast extends Model
{
public function subscribers()
{
return $this->belongsToMany(User::class, Subscription::class);
}
}
class Subscription extends Pivot
{
public function user()
{
return $this->belongsTo(User::class);
}
public function podcast()
{
return $this->belongsTo(Podcast::class);
}
}
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('users', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('podcasts', function (Blueprint $table) {
$table->id();
$table->string('name');
});
Schema::create('podcast_user', function (Blueprint $table) {
$table->foreignIdFor(Podcast::class);
$table->foreignIdFor(User::class);
$table->timestamps();
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Table names
When using Pivot Models for a belongsToMany
relation, pivot tables will be created using Laravel conventions, regardless of the Model name you have set.
To override the table name, declare the table name manually:
models:
User:
podcasts: belongsToMany using:PodcastUser
Podcast:
users: belongsToMany using:PodcastUser
Subscription:
user: belongsTo
podcast: belongsTo
table: subscriptions
2
3
4
5
6
7
8
9
class User extends Model
{
public function podcasts()
{
return $this->belongsToMany(Podcast::class, 'subscriptions')
->using(PodcastUser::class);
}
}
class Podcast extends Model
{
public function users()
{
return $this->belongsToMany(User::class, 'subscriptions')
->using(PodcastUser::class);
}
}
class Subscription extends Pivot
{
protected $table = 'subscriptions';
public function user()
{
return $this->belongsTo(User::class);
}
public function podcast()
{
return $this->belongsTo(Podcast::class);
}
}
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
29
30
31
32
Schema::create('subscriptions', function (Blueprint $table) {
$table->bigUnsignedInteger('user_id');
$table->bigUnsignedInteger('podcast_id');
$table->timestamps();
});
2
3
4
5
Polymorphic Many-to-Many Pivot Models
You may also use Polymorphic Pivot Models in the same way.
For example, here all related models use UUID, but the tag itself uses an integer as primary key. Here the Taggable
model will be changed automatically to MorphPivot
. Since Larawiz will guess that all models that reference a taggables.tagable
are UUID, it will create a uuidMorphs()
column automatically.
models:
Post:
id: uuid
title: string
tags: morphToMany:Tag,taggable using:Taggable
Video:
id: uuid
name: string
tags: morphToMany:Tag,taggable using:Taggable
Tag:
name: string
posts: morphedByMany:Post,taggable
videos: morphedByMany:Video,taggable
Taggable:
tag: belongsTo
taggable: morphTo
timestamps: ~
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Post extends Model
{
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
}
class Video extends Model
{
public function tags()
{
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');
}
}
class Taggable extends MorphPivot
{
public function tag()
{
return $this->belongsTo(Tag::class);
}
public function taggable()
{
return $this->morphTo();
}
}
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
29
30
31
32
33
34
35
36
37
38
39
40
41
Schema::create('posts', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('title');
$table->timestamps();
});
Schema::create('videos', function (Blueprint $table) {
$table->uuid('id')->primary();
$table->string('title');
$table->timestamps();
});
Schema::create('tags', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
Schema::create('taggables', function (Blueprint $table) {
$table->foreignIdFor(Tag::class);
$table->uuidMorphs('taggable');
$table->timestamps();
});
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
Don't repeat yourself
As long as one relation sets the pivot model with using
, the pivot will be created. There is no need to declare using
on all models, buy you may if you need to access the pivot table anyway.
Adding primary keys and timestamps
When creating Pivot models, Primary Keys and Timestamps are disabled.
You can re-enable Primary Keys and Timestamps using the primary
and timestamps
keys, respectively.
models:
User:
subscriptions: belongsToMany:Podcast using:Subscription withTimestamps withPivot:last_heard
# ...
Podcast:
# ...
Subscription:
id: ~ # Re-enabled
user: belongsTo:User
podcast: belongsTo:Podcast
last_heard: timestamps nullable
timestamps: ~ # Re-enabled
2
3
4
5
6
7
8
9
10
11
12
13
class Subscription extends Pivot
{
public $incrementing = true;
protected $casts = ['last_heard' => 'timestamp'];
// ...
}
2
3
4
5
6
7
You can also create your own Pivot model, or a Morphable Pivot model, without any relation pointing to it. Set the type
key to pivot
or morphPivot
, respectively, through a Custom Model.
models:
User:
# ...
Podcast:
# ...
Subscription:
columns:
user: belongsTo
podcast: belongsTo
type: pivot
2
3
4
5
6
7
8
9
10
11
12
class Subscription extends Pivot
{
// ...
}
2
3
4
No soft-deletes
Pivots models do not support soft-deletes.
Declaring softDeletes: ~
in the Pivot Model doesn't do anything, but there is a very low chance Larawiz will summon you into a Nickelback concert.