在這個章節,要介紹 Eloquent ORM ,他是以 Query Builder 為基礎,簡單說就是加強版(強化版),兩者皆是Laravel提供存取資料的方法。

什麼是 Eloquent ORM ?

ORM(Object Relational Mapping)物件和關聯資料庫對應,至物件導向的資料抽象化技術,可能覺得前面這麼長一段,到底在講什麼?簡單的說,就是讓資料庫的每個資料表都對應到屬於自己的Model變成一個物件(Class),也就是Model 跟資料庫的溝通互動(新增、查詢、刪除、修改)。

※ Laravel的相關慣例

  • 一個 resource 對應到資料庫(DB)裡的一個資料表(Table)
  • 一個 model 對應到資料表(Table)裡的一筆資料或一列資料(row)

建立 Eloquent Model

(建立Migration 也一併建立Model,有建立過就可忽略此段)
make:model 後面自訂要對應資料表名稱(資料夾/model名稱 或者 model名稱)。

Model名稱使用英文單數,以大駝峰式命名(Upper Camel Case),首字要大寫

1
$ php artisan make:model Member

建立 Model,也一併建立 migration--migration 可以縮寫成 -m

※ 至於 migration自動產生,他會如何命名? Laravel 預設命名方式:蛇底式命名(Snake Case)

1
$ php artisan make:model Member --migration

專案 > app >

以上Model名稱為 Member

專案 > database > migrations >

資料表名稱為 2020_06_13_103343_create_members_table.php

開啟會員資料表對應的 Eloquent Model
專案 > app > Member.php

1
2
3
4
5
6
7
8
9
10
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Member extends Model
{
//
}

定義 Eloquent Model

Model 自己對應自己的資料表,這是 Laravel 機制,但基本上我還是會寫自己對應的table,以免會有出差錯的情形,算是給自己一個心安吧。

但一定會有疑問,如果我 Model 名稱要跟資料表不一樣名稱可不可以?其實是可以的,我們可以將繼承 Model 的 Class 內,將table 指向需要的資料表 protected $table = '資料表';

1
2
3
4
5
6
7
8
9
10
<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Book extends Model
{
protected $table = 'members';
}

Eloquent: Relationships

Model 定義關聯的資料表,若沒有定義就會指定為Model 名稱小寫的複數

1
2
3
4
5
6
/**
* 模型關聯的資料表
*
* @var string
*/
protected $table = '資料表';

定義主鍵。但基本上如果主鍵是id,可以不用做定義。

1
2
3
4
5
6
/**
* 自行定義資料庫中的主鍵
*
* @var string
*/
protected $primaryKey = '主鍵欄位';

是否將有 AUTO INCREMENT 欄位做自動遞增,僅限用在int的欄位。預設為true,設成false為取消。

1
2
3
4
5
6
/**
* 欄位值有使用 AUTO INCREMENT 自動遞增資料的值
*
* @var bool
*/
public $incrementing = true;

定義主鍵型態。主鍵型態有可能是 string (字串)或是 int (整數),就像是 Email 或是 id

1
2
3
4
5
6
/**
* 定義主鍵類型
*
* @var string
*/
protected $keyType = '型態';

設定時間戳記。時間戳記預設為true,所以使用Seeder 及Factory新增假資料的時候會自動帶入時間。預設為 true,設成false為取消。

1
2
3
4
5
6
7
/**
* 設定模型是否應該被戳記時間。
* default true
*
* @var bool
*/
public $timestamps = true;

資料庫連線方式。有時候一個專案不只用一個資料庫內容,所以可能會有其他多種資料庫連線方式。
專案 > .env

1
2
3
4
5
6
7
/**
* 建立其他連線方式,專案預設資料庫連線可能是MySQL,但可能會遇到專案去使用其他資料庫。
*
*
* @var string
*/
protected $connection = 'connection-name';

日期的儲存格式。

1
2
3
4
5
6
/**
* 模型的日期欄位的儲存格式。
*
* @var string
*/
protected $dateFormat = 'U';

U定義型態可以參考:date - PHP

建立Controller

1
$ php artisan make:controller MemberController

開啟 MemberController.php 的檔案

專案 > app > Http > Controllers > MemberController.php

1
2
3
4
5
6
7
8
9
10
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class MemberController extends Controller
{
//
}
  1. 引入 Member 的 Model,use App\Member;,但如果沒做引入,在做操作時前面就要加上 App,例如:App\User::all()
  2. 在class 裡寫一個 indexfunction

接下來要做資料庫的操作。

1
2
3
4
5
6
7
8
9
10
11
12
13
<?php

namespace App\Http\Controllers;

use App\Member;
use Illuminate\Http\Request;

class MemberController extends Controller
{
public function index(){

}
}

如何使用 Eloquent Model 操作取得資料?

取得資料表所有資料 all()

  • Member 為 Model 的類別名稱。
  • all() 為取得所有資料。 其實我們可以用 get() 來取代 all() ,結果是一樣的。
  • toArray() 將模型轉換成一個陣列。
1
2
3
4
$datas = Member::all();

// 印出資料
dd($datas->toArray());

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
array:11 [▼
0 => array:11 [▼
"id" => 1
"m_account" => "2egcFFaMjf"
"m_password" => "75021831b3ef0dcae0d3ed1e8ec7dd1c"
"m_name" => "Mrs. Maymie Kulas"
"m_id" => "M10001"
"m_email" => "nya.dickinson@example.org"
"m_phone" => "888-373-1217"
"m_login_time" => null
"created_at" => "2020-07-05 07:09:21"
"updated_at" => null
"category" => 1
]
1 => array:11 [▶]
2 => array:11 [▶]
3 => array:11 [▶]
4 => array:11 [▶]
5 => array:11 [▶]
6 => array:11 [▶]
7 => array:11 [▶]
8 => array:11 [▶]
9 => array:11 [▶]
10 => array:11 [▶]
]

取得單一筆資料,且是指定資料表id的資料 find()

find(),參數值為資料表的 id 值。

1
2
3
4
$datas = Member::find(10);

// 印出資料
dd($datas->toArray());

※ 在上一篇(Part 11)的 Query Builder(查詢建構器)有提到 find(),而 Eloquent ORM 也有 find() 他們雖然用法一樣,但是他們是走不同的類別,前者是走 Illuminate/Database/Query/Builder.php ,而後者是走 Illuminate/Database/Eloquent/Builder.php ,但方法其實是一樣的。

1
2
3
4
$datas = Member::findOrFail(10);

// 印出資料
dd($datas->toArray());

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
array:11 [▼
"id" => 10
"m_account" => "gchbObOjsv"
"m_password" => "3242ad2d31797f5aa7fef8034be969ee"
"m_name" => "Rebekah Welch DVM"
"m_id" => "M10001"
"m_email" => "opagac@example.com"
"m_phone" => "888-867-0657"
"m_login_time" => null
"created_at" => "2020-07-05 07:09:21"
"updated_at" => null
"category" => 3
]

findOrFail() 結果雖然與 find() 是一樣的,但是今天若找不到匹配的資料的時候,find() 只會出現 Error,而 findOrFail() 會出現404的訊息,Eloquent ORM 會將此狀況拋出例外(Exception)。

find()findOrFail()first()firstOrFail() 類似,看官們可以參考官方的範例。

條件搜尋 where()

當使用條件搜尋的時候,都是以 get() 取得回傳的 Eloquent Collection 物件。
all()get() 是一樣的,但 where() 後面只能接get() 才會正常執行。

※ 查詢 會員權限 等於 2 的。

1
2
3
4
$datas = Member::where('category', '2')->get();

// 印出資料
dd($datas->toArray());

結果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
array:3 [▼
0 => array:11 [▼
"id" => 4
"m_account" => "WPTnOjHmCa"
"m_password" => "e792f13b29fafbd6755414643e5b08c4"
"m_name" => "Lolita Lind MD"
"m_id" => "M10001"
"m_email" => "zaria.bergnaum@example.com"
"m_phone" => "(877) 379-1398"
"m_login_time" => null
"created_at" => "2020-07-05 07:09:21"
"updated_at" => null
"category" => 2
]
1 => array:11 [▼
"id" => 5
"m_account" => "7TLwP4gj1P"
"m_password" => "48c7c2e24091a4075a3ffcd09b698dc2"
"m_name" => "Evalyn Prohaska"
"m_id" => "M10001"
"m_email" => "botsford.tobin@example.net"
"m_phone" => "888-324-1324"
"m_login_time" => null
"created_at" => "2020-07-05 07:09:21"
"updated_at" => null
"category" => 2
]
2 => array:11 [▶]
]

查詢第一筆資料 first()

1
2
3
4
$datas = Member::first();

// 印出資料
dd($datas->toArray());

上方查詢第一筆資料,但是如果搭配查詢條件(WHERE)的時候,一旦沒查到,他會丟出一個錯誤,但是Laravel 很貼心,寫了一個跟findOrFail() 一樣的函數就是firstOrFail(),一旦做了查詢條件,找不到任何資料,他會針對此件事情做一個拋出例外,也就是 404。

以下程式碼,查詢會員權限,但會員權限的資料只到5,所以6是找不到的,所以就拋出例外。

1
$datas = Member::where('category', '=', 6)->firstOrFail();

取得 N 筆資料 take()

1
2
3
4
$datas = Member::take(3)->get();

// 印出資料
dd($datas->toArray());

計算幾筆資料 count()

1
2
3
4
$datas = Member::count();

// 印出資料
dd($datas);

排序 orderBy()

1
2
3
4
$datas = Member::orderBy('category','asc')->get(); 

// 印出資料
dd($datas->toArray());

排序方式

  • ASC(升冪) = 由小到大
  • DESC(降冪) = 由大至小

顯示SQL語法 toSql()

1
2
3
4
$datas = Member::where('category', '2')->toSql();

// 印出資料
dd($datas);

新增資料 create()

1
2
3
4
5
6
7
8
9
10
11
12
13
$datas = Member::create([
'm_account' => 'Ps_0711',
'm_password' => md5('Ab123456'),
'm_name' => '高帥哥',
'm_id' => 'M10015',
'm_email' => 'Abff66666@hotmail.com',
'm_phone' => '02-00001119',
'created_at' => '2020-07-25 15:09:21',
'category' =>'3'
]);

// 印出資料
dd($datas->toArray());

修改資料 update()

1
$datas = Member::where('m_name','高帥哥')->update(['m_id' => 'M10088']);

刪除資料 delete()

1
$datas = Member::where('m_name','高帥哥')->delete();

顯示生成的SQL語法 (適用 Query Builder 或 Eloquent ORM)

引入 DB 的檔案

1
use Illuminate\Support\Facades\DB;

開啟記錄

1
DB::connection()->enableQueryLog();

資料查詢

1
$datas = Member::where('category', '2')->get();

DB::getQueryLog(),記錄使用過的 sql 語法,使用 dd() 印出

1
dd(DB::getQueryLog());

查詢結果

1
2
3
4
5
6
7
array:1 [▼
0 => array:3 [▼
"query" => "select * from `members` where `category` = ?"
"bindings" => array:1 [▶]
"time" => 3.58
]
]

結論

稍微介紹完 Eloquent 的操作與用法,是不是與 Query builder 很像,就說他根本是Query builder 2.0版本,別錯過下一篇,還有你所不知道的內容。

標籤: w3HexSchool PHP Laravel