Laravel - Eloquent ORM - Getting Started

# 前言

學習一個框架, Ray 的想法是, 在深入理解底層實作的原理之前, 應該先知道這個框架的 使用方法; 先學習怎麼使用這個前人造的輪子, 再學習怎麼樣一個輪子。
所以本篇文章重點在於細讀官方文件, 並將內容理解後以 Q&A 的方式記錄下來, 加速學習以及查詢。



# 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();
  • Answer:
    修改 primary key 為 1 的 User model, 且不觸發任何 model event

# Additional

在 Laravel 中, 如何得到與該 model 相關的 table 的名字?
model->getTable()
// string
Self, this, static 在 PHP 中的差異 Laravel - Database - Seeding

留言

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×