简体   繁体   English

Laravel ManyToMany关系-附加或分离事件

[英]Laravel ManyToMany Relationship - On Attach or Detach events

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. 我有一个关于艺术家的4个模特。 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. 以及哪些艺术品出现在什么场所或事件上,以便我可以轻松地为每个模型调用Venues(),Arts(),Events(),Artists(),我应该得到该收藏。 I have created a pivot table. 我创建了一个数据透视表。 The table contains 4 columns. 该表包含4列。

数据透视表

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. 因此,在这种情况下,您会期望一行没有任何0。 So the table above would be collapsed in about 3 rows. 因此,上表将折叠为约3行。

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() 因此,现在假设我想将一个艺术家与同一个事件(艺术品关系)联系起来,如果我是手动进行的话,最好的方法是搜索某个事件中有艺术品但没有艺术家的地点,然后将艺术家与该事件联系起来-艺术品关系,而不是为艺术家与事件之间的关系以及艺术家与艺术品之间的关系创建新的2行,Laravel目前正在使用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: 让我们逐步写下我们需要的内容,然后编写一些迁移:

  1. In our system, we want to store Artists 在我们的系统中,我们想存储艺术家
  2. Each Artist can have many Artworks 每个艺术家可以有很多 艺术品
  3. An Artwork belongs to an Artist. 艺术品属于艺术家。
  4. Each Artist can visit many Events 每个艺术家可以参观许多 活动
  5. On each Event, there are many Artworks 每场活动都有很多艺术品
  6. An Event is held at one Venue 在一个 地点举行活动
  7. A Venue holds many Events 场地举行许多活动

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 1.创建艺术家表

Schema::create('artists', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('name');
    $table->timestamps();
});

2. Creating the artworks table 2.创建艺术品表

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 3.创建事件表

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 4.创建场地表

Schema::create('venues', function(Blueprint $table)
{
    $table->increments('id');
    $table->string('name');
    $table->string('city');
    $table->timestamps();
});

5. Many artists can visit many events 5.许多艺术家可以参观许多活动

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 6.在许多活动中展示许多艺术品

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: 我们可以通过在数据库中插入一些虚拟数据并使用Psy Shell来处理模型来检查一切是否正常:

$ 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM