Laravel — Eloquent ORM — Getting Started (官方文件翻譯整理)
By: Ray Lee
Tags: Orm, Backend, Laravel, Documentation

Photo by Aaron Burden on Unsplash

# 前言

我喜歡使用 Laravel 開發的感覺, 除了開發快速, 程式碼簡潔且優雅之外, Laravel 框架本身也是一個很好的學習參照物。 本篇主要將官方文件重點整理成 Q&A 的形式呈現, 原子化的概念, 這方式並不適用於每個人, 但若對你有幫助, 我會很開心。

# 版本

Laravel 8.x

# Defining Models

以下的 Laravel command 的意思是？

Example:

php artisan make:model Flight

Answer: 建立一個名為 Flight 的 model

以下的 Laravel command 的意思是？

Example:

php artisan make:model Flight --migration



php artisan make:model Flight -m

Answer:

// 建立一個名為 Flight 的 model, 並建立其 migration

php artisan make:model Flight --migration



// 同上

php artisan make:model Flight -m

以下的 Laravel command 的意思是？

Example:

php artisan make:model Flight --factory

php artisan make:model Flight -f



php artisan make:model Flight --seed

php artisan make:model Flight -s



php artisan make:model Flight --controller

php artisan make:model Flight -c



php artisan make:model Flight -mfsc

Answer:

// 建立 Flight model, 並建立其 Factory

php artisan make:model Flight --factory

// 同上

php artisan make:model Flight -f



// 建立 Flight model, 並建立其 seeder

php artisan make:model Flight --seed

// 同上

php artisan make:model Flight -s



// 建立 Flight model, 並建立其 controlelr

php artisan make:model Flight --controller

// 同上

php artisan make:model Flight -c



// 建立 Flight model, 並建立其 migraiton, factory, seeder, 以及 controller

php artisan make:model Flight -mfsc

# Eloquent Model Conventions

Laravel 中, 假設 model name 為 AirTrafficController, 根據 Laravel Model Convention, table name 應為？

air_traffic_controllers

# Table Names

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

protected $table = 'my_flights';

}

Answer: 指定該 model 所對應的 table

# Primary Keys

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

protected $primaryKey = 'flight_id';

}

Answer: primary key 預設為 id , 可以特別指定

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

public $incrementing = false;

}

Answer: Laravel 預設 primary key 為 id, 且為 auto-incrementing, 會 cast 成 int, 若要使用 non-numeric 或 non-incrementing 的 primary key 的話, 要特別指定為 false

以下的 Laravel example code 的意思是？

Example:

<?php



class Flight extends Model

{

protected $keyType = 'string';

}

Answer: Laravel 預設 primary key 為 id, 且為 auto-incrementing, 會 cast 成 int, 若 primary key 不是 int, 需特別指定 type

# Timestamps

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

public $timestamps = false;

}

Answer: Laravel Eloquent 預設會自動管理 created_at 以及 updated_at 欄位, 若不需 Eloquent 自動管理, 可設為 false

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

protected $dateFormat = 'U';

}

Answer: Laravel 預設 timestamps 有其固定格式, 可特別指定格式, 格式決定儲存在資料庫中的格式以及 serialized 之後的格式

以下的 Laravel example code 的意思是？

Example:

<?php



class Flight extends Model

{

const CREATED_AT = 'creation_date';

const UPDATED_AT = 'last_update';

}

Answer: Laravel 中, 預設儲存 timestamps 的 column 分別是 created_at 以及 updated_at, 可使用以上 example 來自定義

# Database Connection

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

protected $connection = 'connection-name';

}

Answer: Laravel 中, Eloquent Model 會使用預設的 Database connection, 可使用上面的 example 自定義

# Default Attribute Values

以下的 Laravel example code 的意思是？

Example:

<?php

class Flight extends Model

{

protected $attributes = [

'delayed' => false,

];

}

Answer: 設定 Eloquent Model attribute 的預設值

# Retrieving Models

# Adding Additional Constraints

以下的 Laravel example code 的意思是？

Example:

<?php

$flights = App\Models\Flight::all();



foreach ($flights as $flight) {

echo $flight->name;

}

Answer: all() 可取得該 model 的所有 records, 也可使用 query constraints 之後, 使用 get() 取得結果

以下的 Laravel example code 的意思是？

Example:

<?php

$flights = App\Models\Flight::where('active', 1)

->orderBy('name', 'desc')

->take(10)

->get();

Answer: where()->orderBy()->take() 為 constraints, 最後使用 get() 取得資料, 若無 constraints, 可直接使用 all() 取得資料

# Refreshing Models

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::where('number', 'FR 900')->first();



$freshFlight = $flight->fresh();

Answer: fresh() 會從 model 重新取得資料, 不影響 $flight 的內容

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::where('number', 'FR 900')->first();



$flight->number = 'FR 456';



$flight->refresh();



$flight->number; // "FR 900"

Answer: refresh() 會使用 fresh() 取得的 data 將原本的替換掉, 包括 relationship

# Collections

以下的 Laravel example code 的意思是？

Example:

<?php

$flights = $flights->reject(function ($flight) {

return $flight->cancelled;

});

Answer: 將 cancelled 的 model 從 $flights 這個 collection 中移除, 並取代 $flights 也可使用

<?php

$flights->forget(function ($flight) {

return $flight->cancelled;

})

以下的 Laravel 中, 可以 foreach collection 嗎？

可以

# Chunking Results

以下的 Laravel example code 的意思是？

Example:

<?php

Flight::chunk(200, function ($flights) {

foreach ($flights as $flight) {

//

}

});

Answer: 會將 collections 分成 1 個 chunk 200 筆資料, 所以共有幾個 chunk 視乎該 collection 共有幾筆資料, 再將每個 chunk 丟入 closure 執行, 如此一來, 當處理資料數量龐大的 collection 時, 可節省記憶體單次調用量

以下的 Laravel example code 的意思是？

Example:

<?php

Flight::where('departed', true)->chunkById(200, function ($flights) {

$flights->each->update(['departed' => false]);

});

Answer: 一次只取 200 筆 update 以節省 memory, chunkById 會記住上一次 chunk 的 last_id, 並加上 orderById, 下一次只會從 last_id 之後取值; 若只使用 chunk 的話, 會是 offset … limit …, 後者遇到數據量大時, 效能會很差, 前者可以很明顯地增進效能

# Advanced Subqueries

以下的 Laravel example code 的意思是？

Example:

<?php

return Destination::addSelect(['last_flight' => Flight::select('name')

->whereColumn('destination_id', 'destinations.id')

->orderBy('arrived_at', 'desc')

->limit(1)

])->get();

Answer:

<?php

// 新增 last_flight column, 其值為 query Flight table 得來

return Destination::addSelect(['last_flight' => Flight::select('name')

// 這行主要定義, 哪些 last_flight 會對應到哪一個 Destination row

->whereColumn('destination_id', 'destinations.id')

// 依照 arrived_at 排序

->orderBy('arrived_at', 'desc')

// 只取一筆, 即最近的航班

->limit(1)

])->get();

# Retrieving Single Models / Aggregates

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::find(1);



$flight = App\Models\Flight::where('active', 1)->first();



$flight = App\Models\Flight::firstWhere('active', 1);

Answer:

<?php

// 取得符合 primary key 的 model

$flight = App\Models\Flight::find(1);



// 取得符合 where constraint 的第一個 model

$flight = App\Models\Flight::where('active', 1)->first();



// where('active', 1)->first() 的縮寫

$flight = App\Models\Flight::firstWhere('active', 1);

以下的 Laravel example code 的意思是？

Example:

<?php

$flights = App\Models\Flight::find([1, 2, 3]);

Answer: 取得 primary key 符合 array 的 model

以下的 Laravel example code 的意思是？

Example:

<?php

$model = App\Models\Flight::where('legs', '>', 100)

->firstOr(['id', 'legs'], function () {

// ...

});

Answer: 取得符合 (‘legs’, ‘>’, 100) 條件的第一個 model 的 ‘id’ 及 ‘legs’ column, 如果該 model 不可得, 則執行 closure 內的動作

# Not Found Exceptions

以下的 Laravel example code 的意思是？

Example:

<?php

$model = App\Models\Flight::findOrFail(1);



$model = App\Models\Flight::where('legs', '>', 100)->firstOrFail();

Answer:

<?php

// 取得 primary key 為 1 的 model, 如果沒找到, 則 throw 'ModelNotFoundException'

// 如果該 exception 沒有被 caught, 則會回傳 404 給 user

$model = App\Models\Flight::findOrFail(1);



// 取得符合 ('legs', '>', 100) 條件的第一個 model, 如果沒找到, 則 throw 'ModelNotFoundException'

// 如果該 exception 沒有被 caught, 則會回傳 404 給 user

$model = App\Models\Flight::where('legs', '>', 100)->firstOrFail();

# Retrieving Aggregates

以下的 Laravel example code 的意思是？

Example:

<?php

$count = App\Models\Flight::where('active', 1)->count();



$max = App\Models\Flight::where('active', 1)->max('price');

Answer:

<?php

// 取得符合 where('active', 1) 條件的 model 數量

$count = App\Models\Flight::where('active', 1)->count();



// 取得符合 where('active', 1) 條件的 model 中, price column 的最大值

$max = App\Models\Flight::where('active', 1)->max('price');

# Inserting & Updating Models

# Inserts

以下的 Laravel example code 的意思是？

Example:

<?php

namespace App\Http\Controllers;



class FlightController extends Controller

{

public function store(Request $request)

{

// Validate the request...



$flight = new Flight;



$flight->name = $request->name;



$flight->save();

}

}

Answer: 從 $request 取得 name, 在 assign 到 $flight model 的 name attribute, 在執行 save() 存到資料庫 created_at 以及 updated_at 會自動建立

# Updates

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::find(1);



$flight->name = 'New Flight Name';



$flight->save();

Answer: 取得 primary key 為 1 的 model, 再用 save() 更新其 name attribute, updated_at 欄位會自動更新

# Mass Updates

以下的 Laravel example code 的意思是？

Example:

<?php

App\Models\Flight::where('active', 1)

->where('destination', 'San Diego')

->update(['delayed' => 1]);

Answer: 取得符合 where(‘active’, 1), 以及 where(‘destination’, ‘San Diego’) 的 models, 並更新 delayed column 為 1

Laravel 中, 當使用 Eloquent 實施 mass update 時, model events 像是 saving, saved, updating, updated 會被觸發嗎？

不會

# Examining Attribute Changes

以下的 Laravel example code 的意思是？

Example:

<?php

$user = User::create([

'first_name' => 'Taylor',

'last_name' => 'Otwell',

'title' => 'Developer',

]);



$user->title = 'Painter';



$user->isDirty(); // true or false

$user->isDirty('title'); // true or false

$user->isDirty('first_name'); // true or false



$user->isClean(); // true or false

$user->isClean('title'); // true or false

$user->isClean('first_name'); // true or true



$user->save();



$user->isDirty(); // true or false

$user->isClean(); // true or false

Answer:

<?php

$user = User::create([

'first_name' => 'Taylor',

'last_name' => 'Otwell',

'title' => 'Developer',

]);



// 這裡變更了 $user model 的 title attribute, 但尚未更動資料庫

$user->title = 'Painter';



// $user model 的 title attribute 變了, 所以 true

$user->isDirty(); // true

// 同上

$user->isDirty('title'); // true

// first_name attribute 並未更動, 所以 false

$user->isDirty('first_name'); // false



// $user model 已有變更, 所以非 clean

$user->isClean(); // false

// title attribute 已變更, 所以非 clean

$user->isClean('title'); // false

// first_name attribute 並未更動, 所以 clean

$user->isClean('first_name'); // true



// 這邊才真正更動資料庫

$user->save();



// 更動後, model 跟資料庫已同步, 所以 isDirty 為 false

$user->isDirty(); // false



// 更動後, model 跟資料庫已同步, 所以是 clean 的

$user->isClean(); // true

以下的 Laravel example code 的意思是？

Example:

<?php

$user = User::create([

'first_name' => 'Taylor',

'last_name' => 'Otwell',

'title' => 'Developer',

]);



$user->title = 'Painter';

$user->save();



$user->wasChanged(); // true or false

$user->wasChanged('title'); // true or false

$user->wasChanged('first_name'); // true or false

Answer:

<?php

$user = User::create([

'first_name' => 'Taylor',

'last_name' => 'Otwell',

'title' => 'Developer',

]);



// 這邊更動了資料庫

$user->title = 'Painter';

$user->save();



// 資料庫在當次 request cycle 有更動, 故為 true

$user->wasChanged(); // true

// title 有更動, 故為 true

$user->wasChanged('title'); // true

// first_name 並沒有更動, 所以為 false

$user->wasChanged('first_name'); // false

以下的 Laravel example code 的意思是？

Example:

<?php

$user = User::find(1);



$user->name; // John

$user->email; // john@example.com



$user->name = "Jack";

$user->name; // Jack



$user->getOriginal('name'); // 這裡是？

$user->getOriginal(); // 這裡是？

Answer:

<?php

$user = User::find(1);



$user->name; // John

$user->email; // john@example.com



// 這裡變更了 $user model, 但尚未更動資料庫

$user->name = "Jack";

$user->name; // Jack



// 取得變更前的 $user model 的 name attribute

$user->getOriginal('name'); // John

// 取得變更前的 $user model

$user->getOriginal(); // 為更動前的 model array

# Mass Assignment

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



class Flight extends Model

{

protected $fillable = ['name'];

}

Answer: 允許 name column 可以批量 assign, 防止有心人士自帶預料外的參數 assign 到預料外的欄位

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::create(['name' => 'Flight 10']);

Answer: 建立一筆資料, 並取得該 model

以下的 Laravel example code 的意思是？

Example:

<?php

$flight->fill(['name' => 'Flight 22']);

Answer: assign ‘Flight 22’ 到 $flight model 的 name attribute 相當於 $flight->name = ‘Flight 22’;

以下的 Laravel example code 的意思是？

Example:

<?php

$fillable = [

'options->enabled',

];

Answer: 允許 nested JSON attribute “options->enabled” 可被批量 assign

以下的 Laravel example code 的意思是？

Example:

<?php

protected $guarded = [];

Answer: 該 model 內的所有 attribute 都允許 mass assignment

# Other Creation Methods

# firstOrCreate / firstOrNew

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::firstOrCreate(['name' => 'Flight 10']);



$flight = App\Models\Flight::firstOrCreate(

['name' => 'Flight 10'],

['delayed' => 1, 'arrival_time' => '11:30']

);



$flight = App\Models\Flight::firstOrNew(['name' => 'Flight 10']);



$flight = App\Models\Flight::firstOrNew(

['name' => 'Flight 10'],

['delayed' => 1, 'arrival_time' => '11:30']

);

Answer:

<?php

// 使用條件 ['name' => 'Flight 10'] 從資料庫尋找, 若找到則回傳該 model,

// 若沒找到, 則使用 ['name' => 'Flight 10'] 建立該筆資料並回傳該 model

$flight = App\Models\Flight::firstOrCreate(['name' => 'Flight 10']);



// 使用條件 ['name' => 'Flight 10'] 從資料庫尋找, 若找到則回傳該 model,

// 若沒找到, 則使用 ['name => 'Flight 10', 'delayed' => 1, 'arrival_time' => '11:30']

// 建立該筆資料並回傳該 model

$flight = App\Models\Flight::firstOrCreate(

['name' => 'Flight 10'],

['delayed' => 1, 'arrival_time' => '11:30']

);



// 使用條件 ['name' => 'Flight 10'] 從資料庫尋找, 若找到則回傳該 model,

// 若沒找到, 則使用 ['name' => 'Flight 10'] 回傳並建立該 model, 但尚未

// 更新資料庫

$flight = App\Models\Flight::firstOrNew(['name' => 'Flight 10']);



// 使用條件 ['name' => 'Flight 10'] 從資料庫尋找, 若找到則回傳該 model,

// 若沒找到, 則使用 ['name => 'Flight 10', 'delayed' => 1, 'arrival_time' => '11:30']

// 建立該 model, 但尚未更新資料庫

$flight = App\Models\Flight::firstOrNew(

['name' => 'Flight 10'],

['delayed' => 1, 'arrival_time' => '11:30']

);

# updateOrCreate

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::updateOrCreate(

['departure' => 'Oakland', 'destination' => 'San Diego'],

['price' => 99, 'discounted' => 1]

);

Answer:

<?php

// 使用條件 ['departure' => 'Oasland', 'destination' => 'San Diego'] 尋找

// 如果有找到, 更新 ['price' => 99, 'discounted' => 1], 如果沒找到, merge 上面

// 兩個 array 並建立該筆資料

$flight = App\Models\Flight::updateOrCreate(

['departure' => 'Oakland', 'destination' => 'San Diego'],

['price' => 99, 'discounted' => 1]

);

以下的 Laravel example code 的意思是？

Example:

<?php

App\Models\Flight::upsert([

['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],

['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]

], ['departure', 'destination'], ['price']);

Answer:

<?php

// 尋找第一個 arg 中的兩筆 record [['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99], [array 2]]

// 如果沒找到, 則以上面 array 中的資料建立, 如果有找到, 即 duplicate record, 那就更新第三個 arg 中的

// price column, 則判斷是否 exist 的 unique 欄位為第二個 array 中的 ['departure', 'destination']

App\Models\Flight::upsert([

['departure' => 'Oakland', 'destination' => 'San Diego', 'price' => 99],

['departure' => 'Chicago', 'destination' => 'New York', 'price' => 150]

], ['departure', 'destination'], ['price']);

# Deleting Models

以下的 Laravel example code 的意思是？

Example:

<?php

$flight = App\Models\Flight::find(1);



$flight->delete();

Answer: 取得 primary key 為 1 的 model, 並 delete

# Deleting An Existing Model By Key

以下的 Laravel example code 的意思是？

Example:

<?php

App\Models\Flight::destroy(1);



App\Models\Flight::destroy(1, 2, 3);



App\Models\Flight::destroy([1, 2, 3]);



App\Models\Flight::destroy(collect([1, 2, 3]));

Answer:

<?php

// 刪除 primary key 為 1 的 model

App\Models\Flight::destroy(1);



// 同上

App\Models\Flight::destroy(1, 2, 3);



// 同上

App\Models\Flight::destroy([1, 2, 3]);



// 同上

App\Models\Flight::destroy(collect([1, 2, 3]));

以下的 Laravel example code, deleting 以及 deleted event 會被觸發嗎？

Example:

<?php

App\Models\Flight::destroy(1);



App\Models\Flight::destroy(1, 2, 3);



App\Models\Flight::destroy([1, 2, 3]);



App\Models\Flight::destroy(collect([1, 2, 3]));

Answer: 會的, 因為 destroy 會分別載入每個 model, 並呼叫 delete method

# Deleting Models By Query

以下的 Laravel example code 的意思是？

Example:

<?php

$deletedRows = App\Models\Flight::where('active', 0)->delete();

Answer: 刪除符合 where(‘active’, 0) 的 model

以下的 Laravel example code, deleting 以及 deleted event 會被觸發嗎？

Example:

<?php

$deletedRows = App\Models\Flight::where('active', 0)->delete();

Answer: 不會, 因為實際上 model 並沒有被 retrieve

# Soft Deleting

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\SoftDeletes;



class Flight extends Model

{

use SoftDeletes;

}

Answer: 啟用 soft delete, 啟用後當執行 delete(), model 並不會真正被刪除, 而是會在 deleted_at column 增加一筆時間, 如果 deleted_at column 不是 null, 那就代表該筆資料已被 soft deleted

以下的 Laravel example code 的意思是？

Example:

<?php

public function up()

{

Schema::table('flights', function (Blueprint $table) {

$table->softDeletes();

});

}



public function down()

{

Schema::table('flights', function (Blueprint $table) {

$table->dropSoftDeletes();

});

}

Answer:

<?php

public function up()

{

// 增加 deleted_at column

Schema::table('flights', function (Blueprint $table) {

$table->softDeletes();

});

}



public function down()

{

// 刪除 deleted_at column

Schema::table('flights', function (Blueprint $table) {

$table->dropSoftDeletes();

});

}

以下的 Laravel example code 的意思是？

Example:

<?php

if ($flight->trashed()) {

//

}

Answer: 確認該 model 是否被 soft deleted

# Querying Soft Deleted Models

# Including Soft Deleted Models**

以下的 Laravel example code 的意思是？

Example:

<?php

$flights = App\Models\Flight::withTrashed()

->where('account_id', 1)

->get();

Answer: 當 model 被 soft deleted, 預設會被自動從 query 結果中排除, 如果要取得 soft deleted 的 model, 可以使用 withTrashed()

以下的 Laravel example code 的意思是？

Example:

<?php

$flight->history()->withTrashed()->get();

Answer: 取得 $flight model 的所有 history relation model, 包含 soft deleted

# Retrieving Only Soft Deleted Models

以下的 Laravel example code 的意思是？

Example:

<?php

$flights = App\Models\Flight::onlyTrashed()

->where('airline_id', 1)

->get();

Answer: 只取得符合 where(‘airline_id’, 1) 條件的 soft deleted model

# Restoring Soft Deleted Models

以下的 Laravel example code 的意思是？

Example:

<?php

$flight->restore();

Answer: 將 $flight soft deleted model 復原, 換言之, 將 deleted_at column 設為 null

以下的 Laravel example code 的意思是？

Example:

<?php

App\Models\Flight::withTrashed()

->where('airline_id', 1)

->restore();

Answer: restore 符合 where(‘airline_id’, 1) 的所有 model, 即把 deleted_at column 設為 null

以下的 Laravel example code 的意思是？

Example:

<?php

$flight->history()->restore();

Answer: restore $flight model 的 relation history 上的所有 soft deleted model

# Permanently Deleting Models

以下的 Laravel example code 的意思是？

Example:

<?php

$flight->forceDelete();



$flight->history()->forceDelete();

Answer:

<?php

// 強制刪除 $flight, 即真正的刪除這筆資料

$flight->forceDelete();



// 強制刪除 relation history 上的所有 model, 這裡不包含 soft-deleted

// 如果要取得 soft-deleted 需加上 withTrashed()

$flight->history()->forceDelete();

# Replicating Models

以下的 Laravel example code 的意思是？

Example:

<?php

$shipping = App\Models\Address::create([

'type' => 'shipping',

'line_1' => '123 Example Street',

'city' => 'Victorville',

'state' => 'CA',

'postcode' => '90001',

]);



$billing = $shipping->replicate()->fill([

'type' => 'billing'

]);



$billing->save();

Answer:

<?php

// 建立一筆資料, 並 assign 到 $shipping

$shipping = App\Models\Address::create([

'type' => 'shipping',

'line_1' => '123 Example Street',

'city' => 'Victorville',

'state' => 'CA',

'postcode' => '90001',

]);



// 複製 $shipping model, 將 type 替換為 'billing', 並 assign 到 $billing

// replicate 只是複製 model, 並未真正變動資料庫

$billing = $shipping->replicate()->fill([

'type' => 'billing'

]);



// 將 $billing 真正的存進資料庫

$billing->save();

# Query Scopes

Laravel 中, 當我新增 global scope constraint 時, 需要考慮到 soft-deleted 嗎？

不需要, Laravel 會自動處理好

# Global Scopes

# Writing Global Scopes

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Scopes;



use Illuminate\Database\Eloquent\Builder;

use Illuminate\Database\Eloquent\Model;

use Illuminate\Database\Eloquent\Scope;



class AgeScope implements Scope

{

public function apply(Builder $builder, Model $model)

{

$builder->where('age', '>', 200);

}

}

Answer: 新增一個 global scope constraint, 可以在 model 的 booted method 中加入各種新增的 global scope constraint, 加入後, 該 model 取得的 query 都會自動附加 where(‘age’, ‘>’, 200) constraint

# Applying Global Scopes

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use App\Scopes\AgeScope;

use Illuminate\Database\Eloquent\Model;



class User extends Model

{

protected static function booted()

{

static::addGlobalScope(new AgeScope);

}

}

Answer: 在 model 的 booted method 中, 可以將客制好的 global scope constraint AgeScope 附加到該 model, 如此一來, 之後使用 User model 的 query builder 都會自動附加 AgeScope 所定義的 constraint

# Anonymous Global Scopes

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Builder;

use Illuminate\Database\Eloquent\Model;



class User extends Model

{

protected static function booted()

{

static::addGlobalScope('age', function (Builder $builder) {

$builder->where('age', '>', 200);

});

}

}

Answer: 利用 closure 來附加 global scope constraint, 這樣就不必另外定義一個 scope class, 適用於較簡單的 global scope

# Removing Global Scopes

以下的 Laravel example code 的意思是？

Example:

<?php

User::withoutGlobalScope(AgeScope::class)->get();

Answer: 從當次 query 的結果中, 移除 AgeScope 這個 global scope constraints

以下的 Laravel example code 的意思是？

Example:

<?php

User::withoutGlobalScope('age')->get();

Answer: 從當次 query 的結果中, 移除 age 這個 global scope constraints, age 為 closure 方式直接在 model 的 booted method 中定義的

以下的 Laravel example code 的意思是？

Example:

<?php

User::withoutGlobalScopes()->get();



User::withoutGlobalScopes([

FirstScope::class, SecondScope::class

])->get();

Answer:

<?php

// 從當次 User model 的 query 當中移除所有 global scopes

User::withoutGlobalScopes()->get();



// 從當次 User model 的 query 當中移除 array 中的 global scope

User::withoutGlobalScopes([

FirstScope::class, SecondScope::class

])->get();

# Local Scopes

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

public function scopePopular($query)

{

return $query->where('votes', '>', 100);

}



public function scopeActive($query)

{

return $query->where('active', 1);

}

}

Answer: 定義 local scope, 簡單來說, 當我使用 $query->popular() 就會等於 $query->where(‘votes’, ‘>’, 100), 而 $query->active() 便會等於 $query->where(‘active’, 1)

# Utilizing Local Scope

以下的 Laravel example code 的意思是？

Example:

<?php

namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

public function scopePopular($query)

{

return $query->where('votes', '>', 100);

}



public function scopeActive($query)

{

return $query->where('active', 1);

}

}



$users = App\Models\User::popular()->active()->orderBy('created_at')->get();

Answer: popular() 以及 active() 為 local scope, 會使用定義於該 local scope 內 query

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

public function scopePopular($query)

{

return $query->where('votes', '>', 100);

}



public function scopeActive($query)

{

return $query->where('active', 1);

}

}



$users = App\Models\User::popular()->orWhere(function (Builder $query) {

$query->active();

})->get();

Answer: 相當於 $query->where(...)->orWhere(...) constraints, 只不過對象換成了 local scope, 像是 $query->popular()->orActive() , 注意後者語法只是比喻, Laravel 目前沒有提供這樣的用法, 也可使用 orWhere->

以下的 Laravel example code 的意思是？

Example:

<?php

namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

public function scopePopular($query)

{

return $query->where('votes', '>', 100);

}



public function scopeActive($query)

{

return $query->where('active', 1);

}

}



$users = App\Models\User::popular()->orWhere->active()->get();

Answer: 相當於 $query->where(...)->orWhere(...) constraints, 只不過對象換成了 local scope, 像是 $query->popular()->orActive() , 注意後者語法只是比喻, Laravel 目前沒有提供這樣的用法, 也可使用 closure 方式帶入 orWhere()

# Dynamic Scopes

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

public function scopeOfType($query, $type)

{

return $query->where('type', $type);

}

}



$users = App\Models\User::ofType('admin')->get();

Answer: dynamic scopes 概念, 可以動態的帶入參數到 scope 內, 所以 User::ofType('admin')->get() , 就相當於 User::where('type', 'admin')->get()

# Comparing Models

以下的 Laravel example code 的意思是？

Example:

<?php

if ($post->is($anotherPost)) {

//

}

Answer: 比較兩個 model 是否有相同的 primary_key, table, database connection

以下的 Laravel example code 的意思是？

Example:

<?php

if ($post->author()->is($user)) {

//

}

Answer: 比較 $post model 的 author relation model 是否跟 $user model 有相同的 primary_key, table, database connection

# Events

Laravel Eloquent Model 中, retrieved event 什麼時候會被觸發？

當有一個現存 model 從 database 被 retrieve 時

Laravel Eloquent Model 中, creating/created event 什麼時候會被觸發？

當一個 model 第一次被儲存在資料庫時, 只有第一次會觸發

Laravel Eloquent Model 中, updating/updated event 什麼時候會被觸發？

當現存的 model 被更新且呼叫 save()

Laravel Eloquent Model 中, saving/saved event 什麼時候會被觸發？

當 model 被建立或更新都會觸發

# Using Closures

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Model;



class User extends Model

{

protected static function booted()

{

static::created(function ($user) {

//

});

}

}

Answer: 使用 closure 來定義當 created model event 被觸發後所做的事

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Models;



use Illuminate\Database\Eloquent\Model;

use function Illuminate\Events\queueable;



class User extends Model

{



protected static function booted()

{

static::created(queueable(function ($user) {

//

}));

}

}

Answer: 使用 closure 來定義當 created model event 被觸發後所做的事, 並 queue 被觸發的 closure listener

# Observers

以下的 Laravel example command 的意思是？

Example:

php artisan make:observer UserObserver --model=User

Answer: 建立一個 observer, 名為 UserObserver, 對應的 model 為 User model, 可定義一系列 User model 的各種 model event 的 Listener

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Observers;



use App\Models\User;



class UserObserver

{

public function created(User $user)

{

//

}



public function updated(User $user)

{

//

}



public function deleted(User $user)

{

//

}



public function forceDeleted(User $user)

{

//

}

}

Answer:

<?php



namespace App\Observers;



use App\Models\User;



class UserObserver

{

// 當 created model event 被觸發後要做的事

public function created(User $user)

{

//

}



// 當 updated model event 被觸發後要做的事

public function updated(User $user)

{

//

}



// 當 deleted model event 被觸發後要做的事

public function deleted(User $user)

{

//

}



// 當 forceDeleted model event 被觸發後要做的事

public function forceDeleted(User $user)

{

//

}

}

以下的 Laravel example code 的意思是？

Example:

<?php



namespace App\Providers;



use App\Observers\UserObserver;

use App\Models\User;

use Illuminate\Support\ServiceProvider;



class AppServiceProvider extends ServiceProvider

{

public function register()

{

//

}



public function boot()

{

User::observe(UserObserver::class);

}

}

Answer: 在 AppServiceProvider 中註冊 UserObserver, 註冊後 UserObserver 後, 定義於 UserObserver 的 Listener 會開始監聽 User model event

# Muting Events

以下的 Laravel example code 的意思是？

Example:

<?php

use App\Models\User;



$user = User::withoutEvents(function () use () {

User::findOrFail(1)->delete();



return User::find(2);

});

Answer: withoutEvent method 只接受 closure 為參數, 在這個 closure 內執行的任何 code 都不會觸發 model event 範例中刪除 primary key 為 1 的 User model, 但不會觸發任何 model event

# Saving A Single Model Without Event

以下的 Laravel example code 的意思是？

Example:

<?php

$user = User::findOrFail(1);



$user->name = 'Victoria Faith';



$user->saveQuietly();