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

时间:2015-12-08 23:42:36

标签: php laravel many-to-many

我对这个问题的处理可能不是一个好主意。我必须决定是使用多个数据透视表还是只使用一个表数据透视表,并过滤附加和分离事件。

我有4个关于艺术家的模特。这些是;艺术家,场地,活动,艺术品。这些模型可以帮助我确定哪些活动,艺术家去过的场所以及他展出的艺术作品。还有哪些艺术品出现在什么场地或活动中,以便我可以轻松地为每个模型调用场地(),艺术品(),活动(),艺术家(),我应该得到收藏品。我创建了一个数据透视表。该表包含4列。

Pivot table

枢轴系统工作正常,除非您在图像中看到多行被创建,其中单行可能是可感知的。艺术家可以参加在艺术场所举办的活动。所以在这种情况下,你会期望一行没有任何0。因此,上表将折叠成大约3行。

艺术家模特:

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');
}

...
}

艺术作品模型:

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');
}
...
}

事件模型:

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');
}
...
}

场地模特:

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');
}
...
}

只是为了澄清;

对于艺术作品:我应该能够了解艺术品的展示场地和场地。

对于艺术家:我应该能够了解艺术家展示他/她的艺术作品的活动和场地

对于活动:我应该能够了解该活动中的艺术家和艺术家。

对于场地:我应该能够得到艺术家和艺术品在场地的所有内容。

当可以使用单行时,数据透视表会创建多个行。艺术家可以参加活动场地展出艺术品。

编辑: 这关于优化表。作品可能已经附加到表格中的事件作为关系。所以现在假设我想把一个艺术家附加到同一个事件 - 艺术品关系中,如果我手动完成它,那么最好的方法就是搜索一个事件有艺术品但没有艺术家并将艺术家附加到活动的地方 - 艺术品关系,而不是为艺术家创建2个新行,事件关系和艺术家与艺术品之间的关系,Laravel目前正在使用attach()

2 个答案:

答案 0 :(得分:1)

您应该使用许多数据透视表,但在您的情况下,只需要有两个数据透视表。

让我们逐步记下我们需要的东西,然后写一些迁移:

  1. 在我们的系统中,我们希望存储艺术家
  2. 每位艺术家都可以拥有多个 艺术作品
  3. 艺术品属于艺术家。
  4. 每位艺术家都可以访问许多 活动
  5. 在每个活动中,有许多艺术品
  6. 活动 场地
  7. 举行
  8. 场地拥有许多事件
  9. 大胆的一切都描述了我们的实体,斜体描述了我们实体之间的关系。

    现在让我们设计我们的数据库(表格的模式非常基础):

    <强> 1。创建艺术家表

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

    <强> 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。创建活动表

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

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

    <强> 5。许多艺术家可以参观许多活动

    Schema::create('artist_event', function(Blueprint $table)
    {
        $table->integer('artist_id');
        $table->integer('event_id');
        $table->primary(['artist_id', 'event_id']);
    });
    

    <强> 6。许多艺术作品都在许多活动中展出

    Schema::create('artwork_event', function(Blueprint $table)
    {
        $table->integer('artwork_id');
        $table->integer('event_id');
        $table->primary(['artwork_id', 'event_id']);
    });
    

    (在此示例中不处理外键,但您应该设置它们以加快速度。)

    我们的迁移现已完成,并涵盖了我们列表中的每项要求。如您所见,我们只需要两个数据透视表。

    让我们看一下模特:

    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);
        }
    
    }
    

    我们可以通过在数据库中插入一些虚拟数据并使用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,
             },
           },
         ],
       }
    

答案 1 :(得分:0)

Taylor Otwell拒绝为belongsToMany关系添加更改事件,请点击此处https://github.com/laravel/framework/pull/14988 但是这个包解决了一个问题 https://github.com/fico7489/laravel-pivot