遇見 Laravel 的午後(Part 13)
這章節要介紹關聯式資料庫,如果對於資料庫還不熟悉的朋友們,可以參考網路上的資料,可能會說明得很清楚。基礎非常重要,就像是要學會使用Laravel的框架,首先要把PHP的運用要熟悉,才能知道框架為什麼要這樣寫這樣用。
這本可以把你的基礎打好,又有練習題可以練習。
什麼是關聯式資料庫?
我是一個個體,我讀過XX大學,所有大學是一個資料表,學生是一個資料表,但我讀過這所大學,我跟他有一個無法切斷的關聯,這就是關聯式資料庫。
在做關聯的時候,我們要先認識主鍵、外來鍵、索引。
主鍵 (PRIMARY KEY)
定義:
- 唯一值
- 不能重複
- 不得空值
說明:用來明確識別在資料表當中的,每一筆資料是不同的資料。
數量:一個資料表只能有一個。
範例:員工編號、身分證字號等
外來鍵 (FOREIGN KEY)
定義:
- 值可重複
- 可空值
說明:用來與其他資料表做連結。
數量:一個資料表可以多個
唯一索引 (UNIQUE INDEX)
定義:
- 值不得重複
- 可有一個空值
說明:加快資料表查詢及排序速度。
數量:一個資料表可以多個唯一索引
建立關聯的資料表
我們這章要用到以下資料表,共5張表,若沒建立會員資料表及會員類別資料表,請回顧以前的章節唷!
Model名稱使用英文單數,以大駝峰式命名(Upper Camel Case),首字要大寫
建立會員詳細資訊資料表
※ Model 不管有沒有用到,我們還是會一併建立,以防不時之需。
1 | $ php artisan make:model MemberInfo --migration |
開啟剛剛建立的 migrations 檔案。專案 > database > migrations > 2020_07_25_150146_create_member_infos_table.php
將所需要欄位都寫進去, m_id
這個欄位會對應 members
資料表的 id
。
members
資料表 >id
【主鍵】member_infos
資料表 >m_id
【外來鍵】
1 |
|
建立興趣資料表
1 | $ php artisan make:model Interest --migration |
開啟剛剛建立的 migrations 檔案。專案 > database > migrations > 2020_07_26_072000_create_interests_table.php
member_infos
資料表 >m_interest
【外來鍵】interests
資料表 >id
【主鍵】
1 |
|
建立會員的興趣資料表
1 | $ php artisan make:model MemberInterest --migration |
開啟剛剛建立的 migrations 檔案。專案 > database > migrations > 2020_07_28_083727_create_member_interests_table.php
member_interests.m_id
=members.id
member_interests.interest_id
=interests.id
1 |
|
- members 會員資料表
- member_infos 會員詳細資訊資料表
- member_categories 會員類別資料表
- interests 興趣資料表
- member_interests 會員的興趣資料表
建立好的資料表,記得自己填上資料。
Eloquent 關係
一對一
最簡單的就是一對一,一筆會員帳號資料(members) 對上 一筆會員詳細資料(members_infos)。
如下圖,members.id
-> memeber_infos.m_id
。
定義一對一的方法是 Eloquent Model 所提供的 $this->hasOne()
。
1 | return $this->hasOne('路徑\Model名稱(B資料表)', 'B資料表外來鍵欄位','A資料表對應欄位'); |
第三個參數,如果為id
可以做省略,但比較建議都用上面的方法。
1 | return $this->hasOne('路徑\Model名稱(B資料表)', 'B資料表外來鍵欄位'); |
【實際操作】
- A資料表:members
- B資料表:member_infos
開啟會員資料表(A)對應的 Eloquent Model
m_id
為B資料表的外來鍵id
為A資料表主鍵
專案 > app > Member.php
1 |
|
在上面 Eloquent Model
一對一關聯完以後,要做資料庫的操作,開啟 Member
的 Controller
。
※ 不會建立 Controller 的朋友們,請自行到相關的章節閱讀。
1、建立一個 function
命名自行決定,方便了為了之後寫在一起,所以我用 one_to_one
命名。
2、引入 member
的 Eloquent Model
-> use App\Member;
3、查詢會員的第三筆資料
4、$member
定義的就是我們要的第3筆資料,分別要取出會員姓名、會員電話。
5、由於我在 Member
的 Eloquent Model
裡有自訂一個方法 info
,而這info
的方法就是我們設定一對一關聯 member_infos
的資料表。使用 ->info
要從關聯的資料表取出我們要的欄位,分別是會員性別、會員身分證字號、會員地址。
專案 > app > Http > Controllers > MemberController.php
1 |
|
最後記得設定對應的URL。專案 > routes > web.php
1 |
|
執行專案
1 | $ php artisan serve |
http://127.0.0.1:8000/member/one_to_one
查詢結果:
查詢結果列出的「關聯資料表查詢結果」,在定義的 info
做一對一的關聯,回傳的結果會是 object
的型態。
一對一(逆)
一對一(逆),其實只是相反的對應,只是變成會員詳細資料(members_infos) 對上一筆會員帳號資料(members)。
定義一對一(逆)的方法$this->belongsTo()
,第二個參數跟第三個參數跟一對一是一樣的欄位。
1 | return $this->belongsTo('路徑\Model名稱(B資料表)','A資料表對應欄位','B資料表對應欄位'); |
第三個參數,如果為id
可以做省略,但比較建議都用上面的方法。
1 | return $this->belongsTo('路徑\Model名稱(B資料表)','A資料表對應欄位'); |
【實際操作】
- A資料表:member_infos
- B資料表:members
開啟會員詳細資料(A)對應的 Eloquent Model
m_id
為A資料表的外來鍵id
為B資料表主鍵
專案 > app > MemberInfo.php
1 |
|
接下來做資料庫的操作,其實方法跟一對一的一樣,只是反過來而已。
我們一樣在 Member
的 Controller
做資料庫操作。
建立方式都跟一對一一樣,不再贅述。
記得在上方引入 use App\MemberInfo;
專案 > app > Http > Controllers > MemberController.php
1 |
|
設置對應的URL。
專案 > routes > web.php
1 | Route::get('/member/one_to_one_Inverse', 'MemberController@one_to_one_Inverse'); |
http://127.0.0.1:8000/member/one_to_one_Inverse
查詢結果:
一對一
或 一對一(逆)
都查詢同一筆資料,結果都會是一樣的。
一對多
關聯式資料表,最常見的就是一對多,例如「超商」為一個類別,但是他底下可以列出很多「便利商店」。
看下圖,我們有兩個資料表,可是我們「一般會員」就有 3個會員符合。
如何去定義一對多的關聯?
$this->hasMany()
;
1 | return $this->hasMany('路徑\Model名稱(B資料表)', 'B資料表外來鍵欄位','A資料表對應欄位'); |
第三個參數,如果為id
可以做省略。
1 | return $this->hasMany('路徑\Model名稱(B資料表)', 'B資料表外來鍵欄位'); |
【實際操作】
- A資料表:member_categories
- B資料表:members
開啟會員類別(A)對應的 Eloquent Model
id
為A資料表主鍵category
為B資料表的外來鍵
專案 > app > MemberCategory.php
1 |
|
建立一個會員類別的 Controller
,做資料庫的操作。
※ 不會建立 Controller 的朋友們,請自行到相關的章節閱讀。
1、記得引入 use App\MemberCategory;
,下面做法基本上與一對一都差不多,只是差在回傳值的部分。
2、建立一個方法(function) one_to_many
。
3、印出會員等級
4、印出會員名單,由於 $MemberCategory->member
回傳的是陣列,我們要將陣列做一個處理。
※ join()
是將陣列的值組成一個字串,中間可加入其他元素,也可以使用 implode()
,一樣的功能。
專案 > app > Http > Controllers > MemberCategoryController.php
1 |
|
設置對應的URL。
與一對一是設置不同的 Controller ,記得別搞錯了!專案 > routes > web.php
1 | Route::get('/member/one_to_many', 'MemberCategoryController@one_to_many'); |
執行專案
1 | $ php artisan serve |
http://127.0.0.1:8000/member/one_to_many
查詢結果:
上面的查詢結果,在會員的部分,是列出會員的詳細資料,但他們都是一筆一筆資料,在做呼叫方法的時候,回傳的方式是以陣列(array)呈現。
多對一 or 一對多(逆)
跟一對一一樣,我們可以做逆向的關聯,只是這樣會變成多對一的結果。
就像是小明的會員類別是金牌會員,小黑也是金牌會員,小明跟小黑就是代表多的那方,金牌會員就是一的那方。
定義多對一的方法,跟一對一(逆)一樣。
1 | return $this->belongsTo('路徑\Model名稱(B資料表)','A資料表對應欄位','B資料表對應欄位'); |
第三個參數,如果為id
可以做省略,但比較建議都用上面的方法。
1 | return $this->belongsTo('路徑\Model名稱(B資料表)','A資料表對應欄位'); |
【實際操作】
- A資料表:member_categories
- B資料表:members
開啟會員類別(A)對應的 Eloquent Model
id
為A資料表的主鍵category
為B資料表外來鍵
專案 > app > Member.php
1 |
|
接下的做法都跟一對一(逆)關聯一樣。
開啟 MemberCategoryController.php
做資料庫操作。
一定要記得引入 use App\Member;
。
專案 > app > Http > Controllers > MemberCategoryController.php
1 |
|
設置對應的URL。
專案 > routes > web.php
1 | Route::get('/member/one_to_many_Inverse', 'MemberController@one_to_many_Inverse'); |
http://127.0.0.1:8000/member/one_to_many_Inverse
查詢結果:
一對一(逆)、一對多(逆),在關聯所回傳的型態基本上都是以object回傳,跟一對多是不太一樣的。
多對多
所有關聯最複雜的,應該就是多對多了。一位會員可能有很多興趣,所以一筆 memeber
對到一堆interests
。
如何定義多對多的關聯?$this->belongsToMany()
1 = 路徑\Model名稱(C資料表)
2 = 中間資料表(B資料表)
3 = A資料表(本地)對應B資料表的欄位
4 = C資料表對應B資料表的欄位
1 | return $this->belongsToMany('1', '2', '3', '4'); |
【實際操作】
中間資料表(B),主要是做 A 與 C 資料表中間的橋樑,主要放置多選項的興趣。
- A資料表:members
- B資料表:member_interests
- C資料表:interests
開啟會員資料表(A)對應的 Eloquent Model
m_id
為B資料表對應 A資料表的id
interest_id
為B資料表對應 C資料表的id
專案 > app > Member.php
1 |
|
建立一個 會員 的 Controller
,做資料庫的操作。
※ 不會建立 Controller 的朋友們,請自行到相關的章節閱讀。
1、記得引入 use App\Member;
,下面做法基本跟之前做的關聯都差不多。
※ join()
是將陣列的值組成一個字串,中間可加入其他元素,也可以使用 implode()
,一樣的功能。
專案 > app > Http > Controllers > MemberController.php
1 |
|
設置對應的URL。
專案 > routes > web.php
1 | Route::get('/member/many_to_many', 'MemberController@many_to_many'); |
執行專案
1 | $ php artisan serve |
http://127.0.0.1:8000/member/many_to_many
查詢結果:
那至於多對多有沒有相反結果?當然有,就是跟上面一樣而已,只是角色不一樣而已。
結論
在資料庫關聯其實不難,只是複雜了點,但是如果把資料庫熟悉一定程度,其實這些都算是小菜一疊,道路不難走,重點是你用什麼方式去走。
參考文獻
Laravel - EloquentORM - Relationships - 不學會死
標籤: w3HexSchool
PHP
Laravel
原文作者: Sian
原文鏈接: https://dew31794.github.io/2020/08/09/遇見 Laravel 的午後(Part 13)/
版權聲明: 轉載請註明出處(必須保留作者署名及鏈接)