【问题标题】:Laravel ManyToMany Relationship - On Attach or Detach eventsLaravel 多对多关系 - 附加或分离事件
【发布时间】:2016-03-14 02:26:46
【问题描述】:

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

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

枢轴系统工作正常,但您可以在图像中看到创建了多行,其中单行可能很明显。艺术家可以带着艺术品去参加在场地举行的活动。因此,在这种情况下,您会期望一行没有任何 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()

【问题讨论】:

  • 你能提供一些代码吗?到目前为止,您尝试过什么?
  • 真正的问题是什么?
  • 枢轴系统工作正常,除非您在图像中看到创建了多行,其中单行可能很明显。 艺术家可能会带着艺术品去某个场地举办的活动我觉得,他必须重新考虑他的数据库结构。
  • 我已经添加了我的代码示例。

标签: php laravel many-to-many


【解决方案1】:

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

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

  1. 在我们的系统中,我们想要存储艺术家
  2. 每个艺术家可以拥有许多 艺术作品
  3. 艺术品属于艺术家。
  4. 每个艺术家都可以参观许多 活动
  5. 每场活动都有许多艺术品
  6. 一个活动在一个 地点
  7. 一个场地举办许多活动

所有粗体字都描述了我们的实体,所有斜体字都描述了我们的实体之间的关系。

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

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,
         },
       },
     ],
   }

【讨论】:

  • 这太完美了,我正要写一个答案——但这非常详尽。
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 2017-03-02
    • 2018-07-23
    • 2018-06-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-18
    相关资源
    最近更新 更多