多对多关系也是很常用的一种关系,比如一篇文章可以有多个标签,一个标签下也可以有多篇文章,这就是一个典型的多对多的关系。
1 实现多对多关系
多对多关系我们需要三张表,一张是文章另一张是标签,第三章表是它们的中间表 因为多对多关系需要抽离成两个一对多关系嘛。
1.1 文章结构
public function up() { Schema::create('articles', function (Blueprint $table) { $table->increments('id'); $table->string('title'); $table->text('body'); $table->integer('comment_count')->default(0); $table->timestamps(); }); }
1.2 标签结构
public function up() { Schema::create('tags', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->text('content'); $table->timestamps(); }); }
1.3 中间表结构
public function up() { Schema::create('article_tag', function (Blueprint $table) { $table->increments('id'); $table->integer('article_id'); $table->integer('tag_id'); }); }
2 编写关系
2.1 Article
首先我们看看文章模型中的方法:
public function tags() { /** * (其实 我们只需要写第一个参数就OK了) * 第二个参数:中间表名 如果不是article_tag的话 必须指定该参数。 * 第三个参数:外键 如果中间表中不是article_id 必须指定该参数。 * 第四个参数:关联到那个外键 如果不是tag_id 必须指定该参数。 */ return $this->belongsToMany(Tag::class, 'article_tag', 'article_id', 'tag_id'); // return $this->belongsToMany(Tag::class, 'article_tag'); }
然后展示:
Route::get('/', function () { $article = AppArticle::find(16); foreach ($article->tags as $tag) { echo $tag->name . " : " . $tag->content; echo '<hr />'; } });
2.2 Tag
Tag模型的编写跟Article模型一模一样。
public function articles() { /** * 可以完全省略后面的参数。 * return $this->belongsToMany(Article::class); */ return $this->belongsToMany(Article::class, 'article_tag', 'tag_id', 'article_id'); }
展示:
Route::get('/', function () { $tag = AppTag::find(7); foreach ($tag->articles as $article) { echo $article->title . " : " . $article->body; echo '<hr />'; } });