標籤同步
前言
上一節,我們在 UI 上實現對 tag 的選擇,並且可以建立多個 tag 。但是有瑕疵,今天我們就來看看瑕疵是什麼,並解決它。
說明
開發環境:Windows 7
Laravel 版本: 5+
IDE: Phpstorm
上節課,我們實現了給文章打標籤,並且可以打多個標籤。結束的時候,感覺一切都還在接受範圍,但是我提到有一個小瑕疵,不知讀者有無發現。當你編輯文章想修改文章的標籤的時候,發現可以修改,但是儲存之後再看文章,標籤沒變,還是之前的標籤。這是因為什嗎?
本節的內容比較簡單,專門解決這個小瑕疵。解決之前,你最好先看下這個瑕疵。
資料庫檢查
明明修改了,為什麼沒變,我要娶資料庫裡查看一番!
sqlite> select * fromarticles;1|1|2016-03-20 15:05:18|2016-03-20 15:05:18|譚曉龍建立的文章|真的是|2016-03-28 00:00:002|1|2016-04-23 07:00:13|2016-04-23 07:00:13|flashmessage|hello ~ flashmessage|2016-04-25 00:00:003|1|2016-04-23 07:07:34|2016-04-23 07:07:34|flashtest|flashtest|2016-04-25 00:00:004|1|2016-04-23 07:37:10|2016-04-23 07:37:10|session::put|session::put|2016-04-25 00:00:005|1|2016-04-23 07:59:52|2016-04-23 07:59:52|托爾斯泰|托爾斯泰|2016-04-25 00:00:006|1|2016-04-23 08:03:42|2016-04-23 08:03:42|按時打算asda|阿斯達速凍|2016-04-25 00:00:007|1|2016-04-23 08:05:52|2016-04-23 08:05:52|asdasd|asdasdas|2016-04-25 00:00:008|1|2016-04-23 08:21:58|2016-04-23 08:21:58|autodisappear|autodisappear|2016-04-25 00:00:009|1|2016-04-23 08:39:20|2016-04-23 08:39:20|asd|asdasd|2016-04-25 00:00:0010|1|2016-05-01 15:26:08|2016-05-08 14:17:44|asd|asdasdasdasd|2016-05-16 00:00:00sqlite> select * fromarticle_tagwherearticle_id = 10;10|2|2016-05-01 15:26:08|2016-05-01 15:26:0810|3|2016-05-01 15:26:08|2016-05-01 15:26:08
你看哈,我剛才重新編輯的文章是 id 號為 10 的文章,文章名為 asd ,比較樸實無華。在編輯頁刪了一個標籤,原來有兩個,還剩一個按理說。
然後我又通過 select * from article tag where articleid = 10 查詢了一下 id 為 10 的文章的標籤,你看哈,還是兩個,他們的標籤號分別為 2 和 3 。還是兩個,沒刪掉。為什麼呢?
找原因
文章更新的方法是 ArticleControlle.php 裡的 updat() 方法,對吧?看一下該方法,相比較 store() 好像少了點什麼,為什麼跟 store() 方法比較,因為他們的過程差不多。在 store() 方法中比 updat() 方法多了一個 tags->attach() 這個過程。我們試試把該語句添加到 update() 方法管用不管用:
public function update($id,ArticleRequest $request){ $article=Article::findOrFail($id); $article->update($request->all()); $article->tags()->attach($request->input('tag_list')); return redirect('articles'); }
再去文章更新的頁面修改一下文章的標籤,儲存之後再查看文章,發現標籤多了。。。
其實細想一下,這個 $article 的 tags attach 的是什嗎?是 input(‘tag_list’) 裡面的標籤,相當於又把新編輯的對應該文章的標籤存到了資料庫。不信的話,你再通過 sqlit3 命令去查詢一下你剛才編輯的文章的 tag 。肯定變多了。
按照這個思路的話,我們需要把原資料庫中儲存的 tag 進行刪除,然後再添加新的標籤,沒錯,就是這個邏輯。
Laravel 裡除了 attach 這個方法外,還有 attach 的反方法 detach ,通過 detach 我們可以刪除指定的標籤,你可以做個實驗,不過 detach 不是我們要講的。
sync 方法
面對上面的瑕疵,我們的解決思路是先刪乾淨資料庫裡文章對應的 tag , 然後再給文章添加 tag 。相當於,我們先 detach ,然後再 attach 。
不過, Laravel 還有一個方法叫 sync 。敏感的同學已經能腦補它的全稱了,沒錯 synchronize ,“同步” 的意思。當你把 attach 方法直接修改為 sync ,儲存後再編輯文章,修改標籤,儲存再查看文章,一切都恢複正常了:
public function update($id,ArticleRequest $request){ $article=Article::findOrFail($id); $article->update($request->all()); $article->tags()->sync($request->input('tag_list')); return redirect('articles'); }
所以說, attach 是添加標籤,或者綁定標籤; detach 是解除標籤,或刪除標籤; sync 是同步標籤,或者說是標籤的更新。
同理,把 store() 方法裡的 attach 也換成 sync 。
總結
今天解決了一個小瑕疵,並對比了三種方法,分別是 attach detach 和 sync 。
attach 就是給文章添加 tag ,綁定 tag ,追加 tag
detach 就是給文章解除綁定指定的 tag ,刪除 tag
sync 就是用來對文章的 tag 進行同步的。