Laravel多对多关系详解【文章 – 标签】

  • 2019 年 11 月 13 日
  • 筆記

前言

今天弄了一天的关于文章的功能,其中主要卡在文章与标签的多对多的关系纠结中。卡了半天,终于算是解决了,不是很完美,但可以。

新建迁移文件

多对多的关系中,需要三张表。两张主体表、一张这两张表的关系表

这是我是文章表【articles】、标签表【tags】以及关系表【article_tag】

其中关系的命名是[article_tag]而不是tag_article 因为laravel默认是以字母升序排列。可以在定义的时候设置,但何必那么麻烦,按照默认规则来不是很好么?

另外就是,新建迁移文件的顺序也有要求,关系表肯定是最后的,然后文章表和标签表好像随意,但我是先建文章表。

新建文章表

php artisan make:model Model/Article -m

我是新建模型的时候就顺带穿件迁移表了。可以直接php artisan make:migration create_articles_table --create=articles创建。

这里有外键,但是是其他外键,不关我们这里要讲的。

新建标签表

php artisan make:model Model/Tag -m

我是新建模型的时候就顺带穿件迁移表了。

可以看出没有外键。

新建关系表

php artisan make:migration create_article_tag_table --create=article_tag

这里有两个外键,分别是文章表的主键和标签表的主键。

foreign()外键

references():参照字段

on():参照表

onDelete():删除时的执行动作

这里是跟着删除,比如删除了某篇文章,我们将article_tag中包含article_id一样的记录也删除

执行迁移

php artisan migrate

声明Eloquent的关系

Article

Tag

我们使用 $this->belongsToMany() 来表明Eloquent的关系,这里需要注意的是如果你的外键并不是 article_idtag_id ,你需要在第三个参数进行设置,写成类似下面这样:

public function articles()  {      return $this->belongsToMany('AppArticle','conversation_id');  }

创建文章和标签

就是在这里卡了半天。

我先的写法是:

$article = Article::create([      'title' => $input['title'],      'content' => $input['content'],      'category_id' => $input['category_id'],      'introduction' => $input['introduction'],      'author_id' => $input['author_id'],  ]);  $article->tags()->firstOrCreate(['name'=>'tag name']);

嗯,不行,每次创建文章,哪怕标签都一样的,但还是会在tag表新建一个标签。

类似这样:

后来经过查阅多方资料以及官方文档,才发现,想要标签表中的值唯一,而关系表中通过tag_id来标记不能这样写。

而正在的写法是:

$article->tags()->attach($tags);

传入的$tags 不是名称,而是tag表的id,可以是数组

????而我不能在新建文章时直接输入标签名????

于是,系统新建标签的页面就被我改成这样了: