多對多關係的 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 的擴充和應用吧。
希望今天的內容你能吸收消化。共勉。