[Laravel 5 Fundamentals] 21 – Many-to-Many Relationships and Tags

WBOY
Release: 2016-06-20 12:30:01
Original
883 people have browsed it

多对多关系的 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');} 
Copy after login

下面呢,我们去创建一个 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');} 
Copy after login

之所以还同时创建一个 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');                        |} 
Copy after login

保存后,打开命令行,通过 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",    ],  ] 
Copy after login

关联 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))' 
Copy after login

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

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

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

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

就是这样。

再执行 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",    ],  } 
Copy after login

给文章关联完之后,我们再给 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",      ],    ],  ] 
Copy after login

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

总结

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

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

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
About us Disclaimer Sitemap
php.cn:Public welfare online PHP training,Help PHP learners grow quickly!