My approach to this problem may not be a good idea. I have to decided whether to use many pivot tables or just one table pivot table and filter the attach and detach events.
I have 4 models about an artist. These are; Artist, Venue, Event, Artwork. The models are there to help me identify which events, venues an artist has been to and which artwork he has exhibited. And also which artworks appear at what venues or events so that I can easily call the Venues(), Artworks(), Events(), Artists() for each model and I should get the collection. I have created a pivot table. The table contains 4 columns.
The pivot system works fine except as you can see in the image multiple rows are created where a single row may be appreciable. An artist may go to an event held at a venue with an artwork. So in this case you would expect a single row without any 0s. So the table above would be collapsed in about 3 rows.
THE ARTIST MODEL:
class Artist extends Model {
...
public function Artworks (){
return $this->hasMany('App\Artwork','author_id');
}
public function Events (){
return $this->belongsToMany('App\Event', 'exhibits', 'artist', 'event');
}
public function Venues (){
return $this->belongsToMany('App\Venue', 'exhibits', 'artist', 'venue');
}
...
}
THE ARTWORK MODEL:
class Artwork extends Model {
...
public function Events (){
return $this->belongsToMany('App\Event', 'exhibits', 'artwork', 'event');
}
public function Venues (){
return $this->belongsToMany('App\Artist', 'exhibits', 'artwork', 'venue');
}
...
}
THE EVENT MODEL:
class Event extends Model {
...
public function Venue (){
return $this->belongsTo('App\Venue', 'venue_id');
}
public function Artists (){
return $this->belongsToMany('App\Artist', 'exhibits', 'event', 'artist');
}
public function Artworks (){
return $this->belongsToMany('App\Artwork', 'exhibits', 'event', 'artwork');
}
...
}
THE VENUE MODEL:
class Venue extends Model {
...
public function Events (){
return $this->hasMany('App\Event', 'venue');
}
public function Artists (){
return $this->belongsToMany('App\Artist', 'exhibits', 'venue', 'artist');
}
public function Artworks (){
return $this->belongsToMany('App\Artworks', 'exhibits', 'venue', 'artworks');
}
...
}
Just to clarify;
For the Artwork : I should be able to get at what events and venues the artwork has been exhibited.
For the Artist : I should be able to get what events and venues the artist has exhibit his/her artwork
For the Event : I should be able to get what artworks and artists have been at that event.
For the Venue : I should be able to get what artists, and artworks have been at the venue.
The pivot table creates multiple rows when a single row could be used. An artist can attend a venue for an event to exhibit an artwork.
EDIT: This about optimizing the table. An artwork may already be attached to an event in the table as a relationship. So now suppose I wanted to attach an artist to the same event - artwork relationship, if I was doing it manually the best way to do it would be to search for where an event has artwork but no artist and attach the artist to the event - artwork relationship instead of creating a 2 new rows for the artist to event relationship and artist to artwork relationship which Laravel is doing at the moment with attach()
You should use many pivot tables, but in your case, there only have to be two of them.
Lets write down step by step what we need and write some migrations after that:
Everything bold describes our entities, everything italic describes the relationships between our entities.
Now let's design our database (the schemas of the tables are very basic):
1. Creating the artists table
Schema::create('artists', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->timestamps();
});
2. Creating the artworks table
Schema::create('artworks', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
// An artwork belongs to an artist.
// Because we know this, we also know that an artist has many artworks.
$table->integer('artist_id');
$table->timestamps();
});
3. Creating the events table
Schema::create('events', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
// An event is held at a venue.
$table->integer('venue_id');
$table->timestamps();
});
4. Creating the venues table
Schema::create('venues', function(Blueprint $table)
{
$table->increments('id');
$table->string('name');
$table->string('city');
$table->timestamps();
});
5. Many artists can visit many events
Schema::create('artist_event', function(Blueprint $table)
{
$table->integer('artist_id');
$table->integer('event_id');
$table->primary(['artist_id', 'event_id']);
});
6. Many artworks are presented at many events
Schema::create('artwork_event', function(Blueprint $table)
{
$table->integer('artwork_id');
$table->integer('event_id');
$table->primary(['artwork_id', 'event_id']);
});
(Not handling foreign keys in this example, but you should set them in order to speed things up.)
Our migrations are now finished and covers each requirement in our list. As you can see, we only need two pivot tables.
Let's look at the models:
Artist.php
class Artist extends Model
{
public function artworks()
{
return $this->hasMany(Artwork::class);
}
public function events()
{
return $this->belongsToMany(Event::class);
}
}
Artwork.php
class Artwork extends Model
{
public function artist()
{
return $this->belongsTo(Artist::class);
}
public function events()
{
return $this->belongsToMany(Event::class);
}
}
Event.php
class Event extends Model
{
public function artists()
{
return $this->belongsToMany(Artist::class);
}
public function artworks()
{
return $this->belongsToMany(Artwork::class);
}
public function venue()
{
return $this->belongsTo(Venue::class);
}
}
Venue.php
class Venue extends Model
{
public function events()
{
return $this->hasMany(Event::class);
}
}
We can check if everything works by inserting some dummy data in our database and using the Psy Shell to play around with our models:
$ php artisan tinker
Psy Shell v0.6.1 (PHP 7.0.0RC3 — cli) by Justin Hileman
>>> namespace App;
>>> $artist = Artist::find(1);
=> App\Artist {#680
id: 1,
name: "Peter Pan",
created_at: "2015-12-09 01:06:01",
updated_at: "2015-12-09 01:06:01",
}
>>> $artworks = $artist->artworks;
=> Illuminate\Database\Eloquent\Collection {#677
all: [
App\Artwork {#681
id: 1,
name: "Fancy artwork",
artist_id: 1,
created_at: "2015-12-09 01:06:13",
updated_at: "2015-12-09 01:06:13",
},
],
}
>>> $events = $artist->events;
=> Illuminate\Database\Eloquent\Collection {#684
all: [
App\Event {#686
id: 1,
name: "The greatest event ever",
venue_id: 2,
created_at: "2015-12-09 01:05:51",
updated_at: "2015-12-09 01:05:51",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#685
artist_id: 1,
event_id: 1,
},
},
],
}
>>> $event = Event::find(1);
=> App\Event {#692
id: 1,
name: "The greatest event ever",
venue_id: 2,
created_at: "2015-12-09 01:05:51",
updated_at: "2015-12-09 01:05:51",
}
>>> $venue = $event->venue;
=> App\Venue {#689
id: 2,
name: "Venue 2",
city: "Miami",
created_at: "2015-12-09 01:05:30",
updated_at: "2015-12-09 01:05:30",
}
>>> $artworksAtEvent = $event->artworks;
=> Illuminate\Database\Eloquent\Collection {#693
all: [
App\Artwork {#695
id: 1,
name: "Fancy artwork",
artist_id: 1,
created_at: "2015-12-09 01:06:13",
updated_at: "2015-12-09 01:06:13",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#694
event_id: 1,
artwork_id: 1,
},
},
],
}
泰勒·奥特威尔(Taylor Otwell)拒绝添加相关事件以更改belongsToMany关系,在此处查看更多信息https://github.com/laravel/framework/pull/14988,但此程序包解决了问题https://github.com/fico7489/laravel-pivot
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.