当我们创建一个博客程序的时候,我们当然需要能够撰写博客并发布,另外还要给出一种来关联它们的方法。我们可以使用查找功能,但查找功能留到以后再做,这里先介绍使用标签的方式。比如我们给一篇博客添加了标签“PHP”,那么浏览这篇博客的用户可能会想浏览所有带有该标签的博客,这应该如何实现呢?换句话说,应该如何设计数据库与Eloquent模型呢?这就是这一节所要介绍的多对多关系。
在介绍前可以先复习以下第十四节介绍的《Eloquent关系》,其中介绍了一对一与一对多的关系。
打开 /app/Article.php ,添加多对多关系方法:
public function tags(){ return $this->belongsToMany('App\Tag'); }
然后用命令行创建标签的Eloquent Model:
D:\wamp\www\laravel5>php artisan make:model Tag Model created successfully. Created Migration: 2015_07_25_210033_create_tags_table
这条命令会在 /app/ 下生成一个 Tag.php 文件,并且在 /database/migrations/ 下生成一个类似 XXX_create_tags_table.php 的数据库迁移文件,如果没有生成数据库迁移文件的话,可以通过下面的命令行来创建:
D:\wamp\www\laravel5>php artisan make:migration create_tags_table --create=tags
接着修改刚刚生成的数据库迁移文件:
public function up() { Schema::create('tags', function(Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); Schema::create('article_tag', function(Blueprint $table){ $table->integer('article_id')->unsigned()->index(); $table->foreign('article_id')->references('id')->on('articles')->onDelete('cascade'); $table->integer('tag_id')->unsigned()->index(); $table->foreign('tag_id')->references('id')->on('tags')->onDelete('cascade'); $table->timestamps(); }); } public function down() { Schema::drop('tags'); Schema::drop('article_tag'); }
article_tag
的表名命名方法为取两个关联表的表名单数形式,然后按首字母升序排序,用下划线 _ 连接。如表 users
与 roles
的中间表可以命名为 role_user
。接着在命令行下进行数据库迁移:
D:\wamp\www\laravel5>php artisan migrate Migrated: 2015_07_25_210033_create_tags_table
在 App/Tag.php 中添加多对多关系方法:
public function articles(){ return $this->belongsToMany('App\Article'); }
下面用 php artisan tinker
命令行工具来介绍多对多关系,这样看起来更加清楚。
D:\wamp\www\laravel5>php artisan tinker Psy Shell v0.4.1 (PHP 5.5.12 ΓÇö cli) by Justin Hileman >>> $tag = new App\Tag; //创建一个新的tag => <App\Tag #000000003d1f1f780000000013a9ed91> {} >>> $tag->name = 'PHP'; => "PHP" >>> $tag->save(); //保存tag => true >>> App\Tag::all()->toArray(); //获取所有 tags => [ [ "id" => 1, "name" => "PHP", "created_at" => "2015-07-25 21:29:45", "updated_at" => "2015-07-25 21:29:45" ] ] >>> App\Tag::lists('name'); //列出所有tags的名称 => [ "PHP" ]
下面来关联 文章 与 标签:
>>> $article = App\Article::first(); //获取第一篇博客 => <App\Article #000000003d1f1f6b0000000013a9ed91> { id: 1, user_id: 1, title: "This is the first article", body: "This is the first article content.", created_at: "2015-07-25 21:18:08", updated_at: "2015-07-25 21:18:08", published_at: "2015-07-25 00:00:00", excerpt: null } >>> $article->tags()->attach(1); // 把 ID 为 1 的tag关联到刚刚获取的博客 => null
这时查看数据库,发现虽然标签与博客关联上了(有的可能是直接报错,没有添加成功),但是创建时间与修改时间却都是空的。这时需要修改 Article.php 中刚刚添加的 tags()
方法:
public function tags(){ return $this->belongsToMany('App\Tag')->withTimestamps(); }
这时,退出上次的命令行并重新打开(否则刚刚的修改不生效):
D:\wamp\www\laravel5>php artisan tinker Psy Shell v0.4.1 (PHP 5.5.12 ΓÇö cli) by Justin Hileman >>> $article = App\Article::first(); => <App\Article #000000000fac5aa70000000016f5b020> { id: 1, user_id: 1, title: "This is the first article", body: "This is the first article content.", created_at: "2015-07-25 21:18:08", updated_at: "2015-07-25 21:18:08", published_at: "2015-07-25 00:00:00", excerpt: null } >>> $article->tags()->attach(1); => null
这时再次查看数据库,可以看到已经关联成功了。
接着通过命令行来查看多对多关系,获取与给定博客关联的标签:
>>> $article->toArray(); => [ "id" => 1, "user_id" => 1, "title" => "This is the first article", "body" => "This is the first article content.", "created_at" => "2015-07-25 21:18:08", "updated_at" => "2015-07-25 21:18:08", "published_at" => "2015-07-25 00:00:00", "excerpt" => null ] >>> $article->tags->toArray(); //获取博客的所有标签 => [ [ "id" => 1, "name" => "PHP", "created_at" => "2015-07-25 21:29:45", "updated_at" => "2015-07-25 21:29:45", "pivot" => [ "article_id" => 1, "tag_id" => 1, "created_at" => "2015-07-25 21:38:00", "updated_at" => "2015-07-25 21:38:00" ] ] ] >>> $article->toArray(); //已经关联标签的博客数据 => [ "id" => 1, "user_id" => 1, "title" => "This is the first article", "body" => "This is the first article content.", "created_at" => "2015-07-25 21:18:08", "updated_at" => "2015-07-25 21:18:08", "published_at" => "2015-07-25 00:00:00", "excerpt" => null, "tags" => [ [ "id" => 1, "name" => "PHP", "created_at" => "2015-07-25 21:29:45", "updated_at" => "2015-07-25 21:29:45", "pivot" => [ "article_id" => 1, "tag_id" => 1, "created_at" => "2015-07-25 21:38:00", "updated_at" => "2015-07-25 21:38:00" ] ] ] ] >>> $article->tags->lists('name'); //列出该博客所有标签的名称 => [ "PHP" ]
现在进行反向操作,获取与给定标签关联的博客:
>>> $tag = App\Tag::first(); => <App\Tag #0000000051a0274c0000000008cd8bdd> { id: 1, name: "PHP", created_at: "2015-07-25 21:29:45", updated_at: "2015-07-25 21:29:45" } >>> $tag->articles->toArray(); => [ [ "id" => 1, "user_id" => 1, "title" => "This is the first article", "body" => "This is the first article content.", "created_at" => "2015-07-25 21:18:08", "updated_at" => "2015-07-25 21:18:08", "published_at" => "2015-07-25 00:00:00", "excerpt" => null, "pivot" => [ "tag_id" => 1, "article_id" => 1 ] ] ]
可以看到,也获取成功了。本节完!
该篇属于专题:《Laravel 5 基础视频教程学习笔记》
dodo 2015/11/12 15:38
我才发现, 除了前2章,其他和 https: // laracasts.com/series/laravel-5-fundamentals 都是一样的....
Specs 2015/11/12 15:47
@ 就是看的那个视频教程啊~