当前位置:Gxlcms > PHP教程 > [Laravel5Fundamentals]21–Many-to-ManyRelationshipsandTags

[Laravel5Fundamentals]21–Many-to-ManyRelationshipsandTags

时间:2021-07-01 10:21:17 帮助过:24人阅读

多对多关系的 tag 事例

前言

上一节,我们对 flash message 的使用做一个讲解,了解到什么是 flash message,而且会进行简单的使用。本节,我们对数据库多对多的形式,以文章 tags 作为例子进行讲解。

说明

开发环境:Windows 7

Laravel 版本: 5+

IDE: Phpstorm

数据库在,之前我们就对 Laravel 的Eloquent 和Migration 做过两节介绍,而且在Relationships 讲过数据表之间的外键关系,那也是基本的一对多。

本节我们对数据库中的多对多进行一个讲解,而且所举的例子就是 tags ,文章标签。

tags 的引入

现在咱们博客的基本功能已经有了,写文章,发表文章等。但是随着文章越来越多,文章的筛选和管理就成了问题,要是能有 tag 标记每篇文章的关键词,这对文章的管理将是一个很大的改善。

下面我们就来看一下 Eloquent 是怎么实现给文章 tagging 的。

打开的 Article.php ,还记得当初我们为每篇文章(Article)关联作者(User)是在哪个方法吗?算了,你也回答不了,就在最下面的 user() 方法,里面写了一句 belongsTo 就指明了文章所属。该语句与 hasMany 是相对的,文章只能 belongsTo 一个作者,但是一名作者可以 hasMany 文章,就是这么个关系。

但是在 tag 这里,belongsTo 和 hasMany 就有点讲不通了,一篇文章不能只 belongsTo 一个 tag ,应该是 belongsToMany tags 才通顺。

所在在 user() 方法下面再价一个 tags() 方法,如下所示:

public function tags(){  return $this->belongsToMany('App\Tag');} 

下面呢,我们去创建一个 Tag Eloquent model吧。

创建 Tag model类和 Tag 表

在命令行下输入命令:php artisan make:model Tag。

再在命令行下输入命令: php artisan make:migration create tagtable –create=tags

打开这个 create tagtable.php ,在这里创建 tag 表的一些属性或者说列:

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');} 

之所以还同时创建一个 pivot table (即“ article_tag ”表),就是为了相当于一个快速查找表,能把 article 和 tag 联系在一张表中,方便查取。

接下来对 migration 进行执行,在命令行中执行:php artisan migrate

接下来打开 Tag.php,刚创建的。

既然 tag 和 Article 是多对多的关系,那么在 Tag model 类中也应有一个指向 article 的方法:

public function articles(){     return $this->belongsToMany('App\Article');                        |} 

保存后,打开命令行,通过 tinker 来验证是否成功:php artisan tinker

>>> $tag = new App\Tag;=> App\Tag {#646}>>> $tag->name='personal';=> "personal">>> $tag->save();=> true>>> App\Tag::all()->toArray();=> [    [      "id" => 1,      "name" => "personal",      "created_at" => "2016-04-30 13:48:49",      "updated_at" => "2016-04-30 13:48:49",    ],  ] 

关联 article 和 tag

下面我们尝试关联一下这两个表。

在 tinker 模式下:

>>> App\Tag::all()->toArray();=> [    [      "id" => 1,      "name" => "personal",      "created_at" => "2016-04-30 13:48:49",      "updated_at" => "2016-04-30 13:48:49",    ],  ]>>> $article=App\Article::first();=> App\Article {#659    id: "1",    user_id: "1",    created_at: "2016-03-20 15:05:18",    updated_at: "2016-03-20 15:05:18",    title: "谭晓龙创建的文章",    body: "真的是",    published_at: "2016-03-28 00:00:00",  }>>> $article->toArray();=> [    "id" => 1,    "user_id" => "1",    "created_at" => "2016-03-20 15:05:18",    "updated_at" => "2016-03-20 15:05:18",    "title" => "谭晓龙创建的文章",    "body" => "真的是",    "published_at" => "2016-03-28 00:00:00",  ]>>> $article->tags()->attach(1);Illuminate\Database\QueryExceptionwithmessage 'SQLSTATE[23000]: Integrity constraint violation: 19 NOT NULL constraint failed: article_tag.created_at (SQL: insert into "article_tag" ("article_id", "tag_id") values (1, 1))' 

这里的 $article->tags()->attach(1),就是通过 tags() 方法将 id=1 的 tag 绑定(attach)到该 article 上。

不幸的是,我们报错了,原因就是没有创建时间。改一下吧。

打开 Article.php ,找到 tags() 方法,修改成如下:

public function tags(){    return $this->belongsToMany('App\Tag')->withTimestamps();} 

就是这样。

再执行 attach 命令:

>>> $article = App\Article::first();=> App\Article {#655    id: "1",    user_id: "1",    created_at: "2016-03-20 15:05:18",    updated_at: "2016-03-20 15:05:18",    title: "谭晓龙创建的文章",    body: "真的是",    published_at: "2016-03-28 00:00:00",  }>>> $article->tags()->attach(1);      => null>>> DB::select('select * from article_tag');=> [    {#650      +"article_id": "1",      +"tag_id": "1",      +"created_at": "2016-04-30 14:00:31",      +"updated_at": "2016-04-30 14:00:31",    },  ]>>> $article->tags->toArray();=> [    [      "id" => 1,      "name" => "personal",      "created_at" => "2016-04-30 13:48:49",      "updated_at" => "2016-04-30 13:48:49",      "pivot" => [        "article_id" => "1",        "tag_id" => "1",        "created_at" => "2016-04-30 14:00:31",        "updated_at" => "2016-04-30 14:00:31",      ],    ],  ]>>> $article->toArray();=> [    "id" => 1,    "user_id" => "1",    "created_at" => "2016-03-20 15:05:18",    "updated_at" => "2016-03-20 15:05:18",    "title" => "谭晓龙创建的文章",    "body" => "真的是",    "published_at" => "2016-03-28 00:00:00",    "tags" => [      [        "id" => 1,        "name" => "personal",        "created_at" => "2016-04-30 13:48:49",        "updated_at" => "2016-04-30 13:48:49",        "pivot" => [          "article_id" => "1",          "tag_id" => "1",          "created_at" => "2016-04-30 14:00:31",          "updated_at" => "2016-04-30 14:00:31",        ],      ],    ],  ]>>> $article->tags->lists('name');  => Illuminate\Support\Collection {#653    all: [      "personal",    ],  } 

给文章关联完之后,我们再给 tag 关联文章:

>>> $tag=App\Tag::first();=> App\Tag {#666    id: "1",    name: "personal",    created_at: "2016-04-30 13:48:49",    updated_at: "2016-04-30 13:48:49",  }>>> $tag->articles->toArray();=> [    [      "id" => 1,      "user_id" => "1",      "created_at" => "2016-03-20 15:05:18",      "updated_at" => "2016-03-20 15:05:18",      "title" => "谭晓龙创建的文章",      "body" => "真的是",      "published_at" => "2016-03-28 00:00:00",      "pivot" => [        "tag_id" => "1",        "article_id" => "1",      ],    ],  ] 

哈哈,tag 以及你个自动被绑定到了 article ,直接现实了出来。

总结

这就是今天要讲的内容,相当于是对 Relationship 的扩展和应用吧。

希望今天的内容你能吸收消化。共勉。

人气教程排行