[初探後端]No.4 對文章加上多個分類

前言

突然意識到似乎很久沒有上來這邊寫寫文章了,最近都在埋頭練習 PHP 與 MySQL ,實做了一個超級陽春的 job board 與 blog ,初期弄一個簡單的 blog ,自然是沒什麼問題。但隨著需求的提升,就困難許多了,像是「把一篇文章只能有一個分類,變成一篇文章允許多個分類」,這件事情就會讓難度高上不少,而這篇就是記錄這個過程哩,順便也描述一下自己遇到什麼困難。

資料庫架構的調整

做這樣的改變,首當其衝的必然是資料表與資料表之間的關聯,如果「一篇文章只有一個分類」,我們只需要再 article 的資料表內新增一個 categoryID 的欄位,然後需要時,透過 join 查詢這樣就搞定了。

但如果是「一篇文章有多個分類」呢?

  • articles 的資料表內新增一個 categoryID 的欄位,利用字串拼接的方式儲存?
  • 多建立一張資料表以下簡稱 ref 表,儲存文章與類別的關聯性

我最後想想是選擇了第二種方式,感覺比較好。

於是使用 Workbench 規劃如下:

文章的新增 C

主要是 PHP 與 MySQL 與 HTML 上的調整。

  • 新增文章的網頁

由於變成可以選擇多個類別,所以這部份的選單需要變成多選式的,而我也是第一次發現可以再 name 屬性內加上 [] ,使其傳回陣列。

1
2
3
<select multiple="multiple" name="category[]" id="category">  
...
</select>

  • PHP

這部份我是選擇分開處理,因為根據畫的 modal 圖, articles 這張表其實跟類別已經沒什麼關係了,所以我選擇拆成兩段:

  • 先進行文章的新增,取得文章 id
  • 接著於 ref 表內新增文章與類別的關聯

而資料庫部份使用 PDO 來連接,認為比較關鍵的語法就是

1
$pdo->lastInsertId();

這可以讓我取得最後一筆新增的 id ,這樣我就知道新增的那篇文章 id 是多少。

文章的讀取 R

主要是 PHP 與 MySQL 的調整。需要在 admin.php (後台) 把文章資料讀出來,但這部份也是我比較苦惱的,因為對於 SQL 的語法並不是很擅長,這一段雖然我有做出來,但總覺得如果我更熟悉 SQL 語法,應該可以更好做。

  • MySQL

這部份我試了好一陣,總是沒辦法單獨使用 MySQL 就把文章、類別、關聯表的資料漂亮的串好,頂多就串成下面這樣。

1
2
3
4
SELECT a.*, b.name  
FROM articles as a, categories as b, articleandcategory_ref as c
WHERE a.id = c.articleID AND b.id = c.categoryID
ORDER BY a.created_at DESC

但這樣我也不知道該怎麼用,因為我想要得到的結果是,每篇文章只有一筆資料,然後後面會帶上類別名稱這樣。

這部份我卡了很久,後來決定用比較笨的方法,跟新增文章一樣分成兩段:

  • 先取得全部的文章,存成陣列
  • 對這個陣列進行 foreach ,取得每篇文章 id 後,再透過 SQL 語法取得該文章對應的類別,最後插入陣列。

因為不確定這麼做好不好,感覺這樣很沒有效率。

文章的更新 U

主要是 PHP 與 MySQL 與 HTML 上的調整,這部份的 HTML 畫面也讓我卡了好一陣子,原因是當類別變成多選後,進入編輯時需要將對應的類別設定預設選取,這部份會卡關主要是邏輯卡住了,因為我用了兩層的 foreach ,腦袋轉不過來,應該會有更好的解法但我不知道。

這部份我也是不知道有沒有比較好的做法,也不確定我這麼做對不對。因為如果是更新到類別的話,勢必得到 ref 表內做一些查詢、修改,也有可能把原本的 3 個類別改成 2 個類別,那這樣子要怎麼做出相應的處理呢?

所以這部份我後來想到的做法是

  • 先更新文章本身
  • ref 表內刪除所有跟這篇文章的關聯並重建關聯

這麼做的好處就是不用管要怎麼處理了,反正就是重建新的關聯,只是我不確定這麼做好不好就是了,只是這樣子做讓我輕鬆不少。

文章的刪除 D

主要是 PHP 與 MySQL 的調整,不過也不是說想刪除文章就可以直接刪除文章,MySQL 是關聯式資料庫,從 modal 上看來,文章關係到了 ref 表與 comment 表,所以如果直接針對文章做刪除是肯定會失敗的。

所以這部份的做法是:逐一刪除有關聯的部份

  • 透過該文章 ID 刪除 comment 內對應的資料
  • 接著刪除 ref 表內對應的資料
  • 最後才是刪除文章本體

刪除的部份是相對簡單的呢。

心得

折騰了一陣子總算是把功能都做完了,不過卻也開始懷疑這樣的做法 O 不 OK 就是了,但有做出來總是好的!

畢竟先求有再求好,對吧?

非常非常陽春的界面

0%