ORM簡單介紹

在Laravel中,ORM的主要工具是Eloquent。Eloquent提供了一種直覺式的方法來操作資料庫,讓資料表和模型之間建立了一對一或一對多的映射關係。以下是一些ORM操作的基本用法。

ORM資料種類

  • Laravel撈資料幾種類型:

    1. ORM:Eloquent 模型,可以$data->$field和$data[$field],有getter,setter
    2. QueryBuilder:關連數組(ArrayAccess),只能$data->$field,也有getter,setter(僅限一維以下才有,因為是stdClass)
  • Laravel兩種常用特別的資料格式:

    1. Collection: Laravel內建物件,有很多內建用法,但是存取資料基本上以陣列索引訪問為主
    1
    2
    $a = ['a' => 123];
    $a = collect($a);
    1. StdClass: PHP原生的物件,簡單來說就是讓資料可以對象屬性訪問
    1
    2
    $a = ['a' => 123];
    $a = (object) ($a);

使用ORM基本觀念

  1. 使用create、update、fill(批量賦值)時,要先設定fillable(白名單)或guarded(黑名單),否則會無法寫入
1
2
3
4
5
6
7
8
9
protected $fillable = [
'field1',
'field2',
];

protected $guarded = [
'field3',
'field4',
];

ORM常見用法

撈資料常用方法

  1. where常用方法
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
// 基本用法
$query->where('id', '1');

// 如果是多個條件,可以使用陣列表示
// 第一種寫法
$query->where([
['id', '1'],
['date', '<=', date("Y-m-d H:i:s")]
]);

// 第二種寫法
$query->where([
['id' => '1'],
['date' => '<=', date("Y-m-d H:i:s")]
]);

// 如果要把多個條件括號起來,需使用閉包
$query->where(function ($query) {
$query->where('created_at', '>=', date("Y-m-d H:i:s"))
->orWhereNull('created_at');
});

// 如果要多括號條件,可以使用陣列放閉包(可多個)
$query->where([
['id', '1'],
['date', '<=', date("Y-m-d H:i:s")],
function ($query) {
$query->where('created_at', '>=', date("Y-m-d H:i:s"))
->orWhereNull('created_at');
}
]);

// 一次撈出多筆資料
$query->whereIn('id', [1, 2, 3, 4]);

// 一次撈出多筆資料,例如:一次撈出id為1~10的資料
$query->whereBetween('id', [1, 10]);

// 一次撈出多筆資料,例如:一次撈出id不為1~10的資料
$query->whereNotBetween('id', [1, 10]);

// 一次撈出多筆資料,例如:一次撈出沒有created_at的資料
$query->whereNull('created_at');

// 一次撈出多筆資料,例如:一次撈出有created_at的資料
$query->whereNotNull('created_at');

// 一次撈出多筆資料,例如:一次撈出有關聯資料的資料
$query->whereHas('comments');

// 一次撈出多筆資料,例如:一次撈出沒有關聯資料的資料
$query->whereDoesntHave('comments');
  1. 其餘方法
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
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
// 只撈出特定欄位
$resource = $query->select('id');

// 沒有限制撈取欄位,只影響取出資料的格式
$resource = $query->pluck('id');

// 只撈出資料筆數
$resource = $query->count();

// 只撈出是否有資料
$resource = $query->exists();

// 只撈出特定欄位的最大值
$resource = $query->max('id');

// 只撈出特定欄位的最小值
$resource = $query->min('id');

// 只撈出特定欄位的平均值
$resource = $query->avg('id');

// 可將資料轉為QueryBuilder
$resource = $query->toBase();

// 可將資料分批撈出
$query->chunk(100, function ($resource) {
foreach ($resource as $value) {
// do something
}
});

// 可在操作資料時,做額外的動作
$query->tap(function ($query) use ($request) {
if ($request->has('search') && $request->search != '') {
$query->where('title', 'like', '%' . $request->search . '%');
}
});

// 可拿到與comments關聯的post資料
$posts = App\Post::has('comments')->get();

// 跟上面不同的是,這個是拿到comments資料
$comments = $post->comments;

// 可拿到與comments沒有關聯的post資料
$posts = App\Post::doesntHave('comments')->get();

// 與doesntHave很像,但是這可以使用where條件(第二參數也可帶閉包)
$resource = $query->whereDoesntHave('comments');
  1. 善用with,可以一次撈出多筆資料,例如:一次撈出user、profile、posts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 這樣寫會有N+1問題
$users = User::all();

foreach ($users as $user) {
echo $user->profile->name;
echo $user->posts->title;
}

// 這樣寫就不會有N+1問題
$users = User::with(['profile', 'posts'])->get();

foreach ($users as $user) {
echo $user->profile->name;
echo $user->posts->title;
}

# with其他用法

// 一次撈出多個關聯資料
$query->with(['data', 'data2']);

// 一次撈出多個關聯資料(包含軟刪除資料)
$query->withTrashed(['data', 'data2']);

CUD常用方法

  1. create、update、delete常用方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 基本用法
$model->create([
'field1' => 'value1',
'field2' => 'value2',
]);

// 基本用法
$model->update([
'field1' => 'value1',
'field2' => 'value2',
]);

// 基本用法
$model->delete();

// 基本用法
$model->forceDelete();

// 基本用法
$model->restore();
  1. 假捨想要無視批量賦值的限制,可以使用forceFill、forceCreate、forceUpdate
1
2
3
4
5
6
7
8
9
10
11
12
13
14
$model->forceFill([
'field1' => 'value1',
'field2' => 'value2',
]);

$model->forceCreate([
'field1' => 'value1',
'field2' => 'value2',
]);

$model->forceUpdate([
'field1' => 'value1',
'field2' => 'value2',
]);
  1. 複製資料
1
2
3
4
5
// 基本用法
$model->replicate();

// 基本用法
$model->replicate()->save();
  1. 使用create、update、delete時,會自動更新updated_at欄位,如果不想要更新,可以使用updateTimestamps(),但是要注意,這個方法會把created_at、updated_at都設為null
1
2
$model->updateTimestamps();
$model->save();

其餘常用方法

  1. 要把撈出的資料刪除,一樣使用迴圈unset
1
2
3
foreach ($resource as $key => $value) {
unset($resource[$key]);
}