Laravel多态关系多对多

时间:2019-02-27 16:01:40

标签: php laravel eloquent polymorphism

我在弄清多态关系时遇到了一些麻烦。 我已经阅读了文档,但对我来说却很混乱。

希望每个人都有时间帮助我加深对它的理解。 我想做的是为某些墙纸建立一个非常简单的标签系统。

我开始一个新的测试项目只是为了使它工作。

我有3种型号:墙纸,标签和墙纸标签

class Wallpaper extends Model
{

    protected $primaryKey = 'wallpaper_id';
    protected $table = 'wallpapers';
    protected $guarded = ['wallpaper_id'];

    /**
     * Get all the tags assigned to this wallpaper
     */
    public function tags()
    {
        //
    }

}

class Tag extends Model
{

    protected $primaryKey = 'tag_id';
    protected $table = 'tags';
    protected $guarded = ['tag_id'];

    /**
     * Get all wallpapers that have this given tag
     */
    public function wallpapers()
    {
        //
    }
}

class WallpaperTag extends Model
{

    protected $primaryKey = 'wallpaper_tag_id';
    protected $table = 'wallpaper_tags';
    protected $guarded = ['wallpaper_tag_id'];

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     * Wallpaper relation
     */
    public function wallpaper()
    {
        return $this->belongsTo('App\Wallpaper','wallpaper_id');
    }

    /**
     * @return \Illuminate\Database\Eloquent\Relations\BelongsTo
     * Tag relation
     */
    public function tag()
    {
        return $this->belongsTo('App\Tag','tag_id');
    }

}

此测试项目中的桌布表仅包含wallpaper_id
标签表包含一个tag_id和一个tag
wallet_tags表包含tags.tag_idwallpapers.wallpaper_id的外键

我已经这样设置,以便墙纸可以共享标签而无需重复标签。问题是我真的不了解documentation中的多态关系和示例。

这里有人可以“汤匙喂食”如何工作吗? :')预先感谢您的所有帮助。

1 个答案:

答案 0 :(得分:2)

因此,您尝试使用ManyToMany创建2个表之间的关系,而DB中需要第3个表来创建这种关系。

这是由于一个Wallpaper可以有多个Tag,反之亦然!为此,您需要第三个表来相应地保存该信息。

第3个表仅包含与您的2个主表相关的ID。这可以提供您所需要的灵活性,而对象表实际上可以保存特定于它们的信息,而不必重复这些信息。

如果要在两个表上都存储关系ID,则将被迫复制数据,而这只是您不希望在数据库上执行的操作!想象一下必须更新1000行,因为它基本上是同一张墙纸,但标签却太多了。

无论如何,下面是应该帮助您的代码:

  1. 您确实需要创建一个类来表示您的关系表(WallpaperTag类上的荣誉!就是那个!);
  2. 您不再触摸该类,不要添加归属或任何其他功能!
  3. 您可以在主要类WallpaperTag上创建关系;
    class Wallpaper extends Model
    {
        ...
        public function tags()
        {
            return $this->belongsToMany('App\Tag', 'wallpaper_tag', 'tag_id', 'wallpaper_id');
        }
    }

    class Tag extends Model
    {
        ...
        public function wallpapers()
        {
            return $this->belongsToMany('App\Wallpaper', 'wallpaper_tag', 'wallpaper_id', 'tag_id');
        }
    }

    class WallpaperTag extends Model
    {

    }

Laravel应该在您的类之间创建一个关系,并将其映射到正确的第三张表,以便为您排序搜索。

如果您遵循语义,那么您所需要的只是类名。如果要更改id,则您需要开始告诉Laravel在偏离正常行为时应查找的id列名称。它仍然找到它,只需要名称上的一些指导即可!因此,为什么我们开始向关系belongsTohasMany等添加更多参数:)

数据透视表迁移

您不需要数据透视表ID,因为您的主键是其他表中的两个外键的组合。

  $table->bigInteger('wallpaper_id')->unsigned()->nullable();
  $table->foreign('wallpaper_id')->references('wallpaper_id')
        ->on('wallpaper')->onDelete('cascade');

  $table->bigInteger('tag_id')->unsigned()->nullable();
  $table->foreign('tag_id')->references('tag_id')
        ->on('tags')->onDelete('cascade');

让我知道它是否有帮助! :3