今天弄了一天的关于文章的功能,其中主要卡在文章与标签的多对多的关系纠结中。卡了半天,终于算是解决了,不是很完美,但可以。
多对多的关系中,需要三张表。两张主体表、一张这两张表的关系表。
这是我是文章表
【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
我们使用 $this->belongsToMany()
来表明Eloquent的关系,这里需要注意的是如果你的外键并不是 article_id
和 tag_id
,你需要在第三个参数进行设置,写成类似下面这样:
public function articles()
{
return $this->belongsToMany('App\Article','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,可以是数组
????而我不能在新建文章时直接输入标签名????
于是,系统新建标签的页面就被我改成这样了: