2016年10月5日 星期三

[Laravel 5 教程学习笔记] 十九、多对多关系-标签

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


from : http://9iphp.com/web/laravel/laravel-5-many-to-many-relations.html

沒有留言:

wibiya widget