溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Laravel5.7 Eloquent ORM怎么用

發(fā)布時間:2021-08-06 10:09:06 來源:億速云 閱讀:138 作者:小新 欄目:開發(fā)技術(shù)

小編給大家分享一下Laravel5.7 Eloquent ORM怎么用,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

簡介

Laravel 內(nèi)置的 Eloquent ORM 提供了一個美觀、簡單的與數(shù)據(jù)庫打交道的 ActiveRecord 實現(xiàn),每張數(shù)據(jù)表都對應(yīng)一個與該表進(jìn)行交互的模型(Model),通過模型類,你可以對數(shù)據(jù)表進(jìn)行查詢、插入、更新、刪除等操作。

在開始之前,確保在 config/database.php 文件中配置好了數(shù)據(jù)庫連接。

定義模型

我們從創(chuàng)建一個 Eloquent 模型開始,模型類通常位于 app 目錄下,你也可以將其放在其他可以被 composer.json 文件自動加載到的地方。所有 Eloquent 模型都繼承自 Illuminate\Database\Eloquent\Model 類。

創(chuàng)建模型實例最簡單的辦法就是使用 Artisan 命令 make:model:

php artisan make:model Flight

如果你想要在生成模型時生成數(shù)據(jù)庫遷移,可以使用 --migration 或 -m 選項:

php artisan make:model Flight --migration
php artisan make:model Flight -m

Eloquent 模型約定

現(xiàn)在,讓我們來看一個 Flight 模型的例子,我們將用該類獲取和存取數(shù)據(jù)表 flights 中的信息:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 //
}

表名

注意我們并沒有告訴 Eloquent 我們的 Flight 模型使用哪張表,默認(rèn)規(guī)則是小寫的模型類名復(fù)數(shù)格式作為與其對應(yīng)的表名(除非在模型類中明確指定了其它名稱)。所以,在本例中,Eloquent 認(rèn)為 Flight 模型存儲記錄在 flights 表中。你也可以在模型中定義 table 屬性來指定自定義的表名:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 /**
  * 關(guān)聯(lián)到模型的數(shù)據(jù)表
  *
  * @var string
  */
 protected $table = 'my_flights';
}

主鍵

Eloquent 默認(rèn)每張表的主鍵名為 id,你可以在模型類中定義一個 $primaryKey 屬性來覆蓋該約定。

此外,Eloquent 默認(rèn)主鍵字段是自增的整型數(shù)據(jù),這意味著主鍵將會被自動轉(zhuǎn)化為 int 類型,如果你想要使用非自增或非數(shù)字類型主鍵,必須在對應(yīng)模型中設(shè)置 $incrementing 屬性為 false,如果主鍵不是整型,還要設(shè)置 $keyType 屬性值為 string。

時間戳

默認(rèn)情況下,Eloquent 期望 created_at 和 updated_at 已經(jīng)存在于數(shù)據(jù)表中,如果你不想要這些 Laravel 自動管理的數(shù)據(jù)列,在模型類中設(shè)置 $timestamps 屬性為 false:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 /**
  * 表明模型是否應(yīng)該被打上時間戳
  *
  * @var bool
  */
 public $timestamps = false;
}

如果你需要自定義時間戳格式,設(shè)置模型中的 $dateFormat 屬性。該屬性決定日期被如何存儲到數(shù)據(jù)庫中,以及模型被序列化為數(shù)組或 JSON 時日期的格式:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 /**
  * 模型日期列的存儲格式
  *
  * @var string
  */
 protected $dateFormat = 'U';
}

如果你需要自定義用于存儲時間戳的字段名稱,可以在模型中設(shè)置 CREATED_AT 和 UPDATED_AT 常量:

<?php

class Flight extends Model
{
 const CREATED_AT = 'creation_date';
 const UPDATED_AT = 'last_update';
}

數(shù)據(jù)庫連接

默認(rèn)情況下,所有的 Eloquent 模型使用應(yīng)用配置中的默認(rèn)數(shù)據(jù)庫連接,如果你想要為模型指定不同的連接,可以通過 $connection 屬性來設(shè)置:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 /**
  * The connection name for the model.
  *
  * @var string
  */
 protected $connection = 'connection-name';
}

獲取模型

創(chuàng)建完模型及其關(guān)聯(lián)的數(shù)據(jù)表后,就可以從數(shù)據(jù)庫中獲取數(shù)據(jù)了。將 Eloquent 模型看作功能強大的查詢構(gòu)建器,你可以使用它來流暢的查詢與其關(guān)聯(lián)的數(shù)據(jù)表。例如:

<?php

use App\Flight;

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

foreach ($flights as $flight) {
 echo $flight->name;
}

添加額外約束

Eloquent 的 all 方法返回模型表的所有結(jié)果,由于每一個 Eloquent 模型都是一個查詢構(gòu)建器,你還可以添加約束條件到查詢,然后使用 get 方法獲取對應(yīng)結(jié)果:

$flights = App\Flight::where('active', 1)
    ->orderBy('name', 'desc')
    ->take(10)
    ->get();

注:由于 Eloquent 模型本質(zhì)上就是查詢構(gòu)建器,你可以在 Eloquent 查詢中使用查詢構(gòu)建器的所有方法。

集合

對 Eloquent 中獲取多個結(jié)果的方法(比如 all 和 get)而言,其返回值是 Illuminate\Database\Eloquent\Collection 的一個實例,Collection 類提供了多個有用的函數(shù)來處理 Eloquent 結(jié)果集:

$flights = $flights->reject(function ($flight) {
 return $flight->cancelled;
});

當(dāng)然,你也可以像數(shù)組一樣循環(huán)遍歷該集合:

foreach ($flights as $flight) {
 echo $flight->name;
}

組塊結(jié)果集

如果你需要處理數(shù)據(jù)量很大的 Eloquent 結(jié)果集,可以使用 chunk 方法。chunk 方法會獲取一個指定數(shù)量的 Eloquent 模型“組塊”,并將其填充到給定閉包進(jìn)行處理。使用 chunk 方法在處理大量數(shù)據(jù)集合時能夠有效減少內(nèi)存消耗:

Flight::chunk(200, function ($flights) {
 foreach ($flights as $flight) {
  //
 }
});

傳遞給該方法的第一個參數(shù)是你想要獲取的“組塊”數(shù)目,閉包作為第二個參數(shù)被傳入用于處理每個從數(shù)據(jù)庫獲取的組塊數(shù)據(jù)。

使用游標(biāo)

cursor 方法允許你使用游標(biāo)迭代處理數(shù)據(jù)庫記錄,一次只執(zhí)行單個查詢,在處理大批量數(shù)據(jù)時,cursor 方法可大幅減少內(nèi)存消耗:

foreach (Flight::where('foo', 'bar')->cursor() as $flight) {
 //
}

獲取單個模型/聚合結(jié)果

當(dāng)然,除了從給定表中獲取所有記錄之外,還可以使用 find 和 first 獲取單個記錄。這些方法返回單個模型實例而不是模型集合:

// 通過主鍵獲取模型...
$flight = App\Flight::find(1);

// 獲取匹配查詢條件的第一個模型...
$flight = App\Flight::where('active', 1)->first();

還可以通過傳遞主鍵數(shù)組來調(diào)用 find 方法,這將會返回匹配記錄集合:

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

Not Found 異常

有時候你可能想要在模型找不到的時候拋出異常,這在路由或控制器中非常有用,findOrFail 和 firstOrFail 方法會獲取查詢到的第一個結(jié)果。不過,如果沒有任何查詢結(jié)果,Illuminate\Database\Eloquent\ModelNotFoundException 異常將會被拋出:

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

如果異常沒有被捕獲,那么 HTTP 404 響應(yīng)將會被發(fā)送給用戶,所以在使用這些方法的時候沒有必要對返回 404 響應(yīng)編寫額外的檢查:

Route::get('/api/flights/{id}', function ($id) {
 return App\Flight::findOrFail($id);
});

獲取聚合結(jié)果

當(dāng)然,你還可以使用查詢構(gòu)建器提供的聚合方法,例如 count、sum、max,以及其它查詢構(gòu)建器提供的聚合函數(shù)。這些方法返回計算后的結(jié)果而不是整個模型實例:

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

插入/更新模型

插入

想要在數(shù)據(jù)庫中插入新的記錄,只需創(chuàng)建一個新的模型實例,設(shè)置模型的屬性,然后調(diào)用 save 方法:

<?php

namespace App\Http\Controllers;

use App\Flight;
use Illuminate\Http\Request;
use App\Http\Controllers\Controller;

class FlightController extends Controller{
 /**
  * 創(chuàng)建一個新的航班實例
  *
  * @param Request $request
  * @return Response
  * @translator laravelacademy.org
  */
 public function store(Request $request)
 {
  // 驗證請求...

  $flight = new Flight;

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

  $flight->save();
 }
}

在這個例子中,我們只是簡單分配 HTTP 請求中的 name 參數(shù)值給 App\Flight 模型實例的 name 屬性,當(dāng)我們調(diào)用 save 方法時,一條記錄將會被插入數(shù)據(jù)庫。created_at 和 updated_at 時間戳在 save 方法被調(diào)用時會自動被設(shè)置,所以沒必要手動設(shè)置它們。

更新

save 方法還可以用于更新數(shù)據(jù)庫中已存在的模型。要更新一個模型,應(yīng)該先獲取它,設(shè)置你想要更新的屬性,然后調(diào)用 save 方法。同樣,updated_at 時間戳?xí)蛔詣痈?,所以沒必要手動設(shè)置其值:

$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();

批量更新

更新操作還可以同時修改給定查詢提供的多個模型實例,在本例中,所有有效且 destination=San Diego 的航班都被標(biāo)記為延遲:

App\Flight::where('active', 1)
  ->where('destination', 'San Diego')
  ->update(['delayed' => 1]);

update 方法要求以數(shù)組形式傳遞鍵值對參數(shù),代表著數(shù)據(jù)表中應(yīng)該被更新的列。

注:通過 Eloquent 進(jìn)行批量更新時,saved 和 updated 模型事件將不會在更新模型時觸發(fā)。這是因為在進(jìn)行批量更新時并沒有從數(shù)據(jù)庫獲取模型。

批量賦值

還可以使用 create 方法保存一個新的模型。該方法返回被插入的模型實例。但是,在此之前,你需要指定模型的 fillable 或 guarded 屬性,因為所有 Eloquent 模型都通過批量賦值(Mass Assignment)進(jìn)行保護(hù),這兩個屬性分別用于定義哪些模型字段允許批量賦值以及哪些模型字段是受保護(hù)的,不能顯式進(jìn)行批量賦值。

當(dāng)用戶通過 HTTP 請求傳遞一個不被期望的參數(shù)值時就會出現(xiàn)安全隱患,然后該參數(shù)以不被期望的方式修改數(shù)據(jù)庫中的字段值。例如,惡意用戶通過 HTTP 請求發(fā)送一個 is_admin 參數(shù),然后該參數(shù)映射到模型的 create 方法,從而允許用戶將自己變成管理員。

所以,你應(yīng)該在模型中定義哪些屬性是可以進(jìn)行賦值的,使用模型上的 $fillable 屬性即可實現(xiàn)。例如,我們設(shè)置 Flight 模型上的 name 屬性可以被賦值:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 /**
  * 可以被批量賦值的屬性.
  *
  * @var array
  */
 protected $fillable = ['name'];
}

設(shè)置完可以被賦值的屬性之后,我們就可以使用 create 方法在數(shù)據(jù)庫中插入一條新的記錄。create 方法返回保存后的模型實例:

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

如果你已經(jīng)有了一個模型實例,可以使用 fill 方法通過數(shù)組屬性來填充:

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

黑名單屬性

$fillable 就像是可以被賦值屬性的“白名單”,還可以選擇使用 $guarded。$guarded 屬性包含你不想被賦值的屬性數(shù)組。所以不被包含在其中的屬性都是可以被賦值的,因此,$guarded 功能就像“黑名單”。當(dāng)然,這兩個屬性你只能同時使用其中一個而不能一起使用,因為它們是互斥的。下面的例子中,除了 price 之外的所有屬性都是可以賦值的:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Flight extends Model
{
 /**
  * 不能被批量賦值的屬性
  *
  * @var array
  */
 protected $guarded = ['price'];
}

如果你想要讓所有屬性都是可批量賦值的,可以將 $guarded 屬性設(shè)置為空數(shù)組:

/**
 * The attributes that aren't mass assignable.
 *
 * @var array
 */
protected $guarded = [];

其它創(chuàng)建方法

firstOrCreate/firstOrNew

還有其它兩種可以用來創(chuàng)建模型的方法:firstOrCreate 和 firstOrNew。firstOrCreate 方法先嘗試通過給定列/值對在數(shù)據(jù)庫中查找記錄,如果沒有找到的話則通過給定屬性創(chuàng)建一個新的記錄。

firstOrNew 方法和 firstOrCreate 方法一樣先嘗試在數(shù)據(jù)庫中查找匹配的記錄,如果沒有找到,則返回一個新的模型實例。需要注意的是,通過 firstOrNew 方法返回的模型實例并沒有持久化到數(shù)據(jù)庫中,你還需要調(diào)用 save 方法手動持久化:

// 通過屬性獲取航班, 如果不存在則創(chuàng)建...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);

// 通過name獲取航班,如果不存在則通過name和delayed屬性創(chuàng)建...
$flight = App\Flight::firstOrCreate(
 ['name' => 'Flight 10'], ['delayed' => 1]
);

// 通過屬性獲取航班, 如果不存在初始化一個新的實例...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);

// 通過name獲取,如果不存在則通過name和delayed屬性創(chuàng)建新實例...
$flight = App\Flight::firstOrNew(
 ['name' => 'Flight 10'], ['delayed' => 1]
);

updateOrCreate

與此類似的,你還會碰到如果模型已存在則更新,否則創(chuàng)建新模型的場景,Laravel 提供了一個 updateOrCreate 方法來一步完成。和 firstOrCreate 方法一樣,updateOrCreate 方法會持久化模型,所以無需調(diào)用 save():

// 如果有從奧克蘭到圣地亞哥的航班則將價格設(shè)置為 $99
// 如果沒有匹配的模型則創(chuàng)建之
$flight = App\Flight::updateOrCreate(
 ['departure' => 'Oakland', 'destination' => 'San Diego'],
 ['price' => 99]
);

刪除模型

要刪除一個模型,調(diào)用模型實例上的 delete 方法:

$flight = App\Flight::find(1);
$flight->delete();

通過主鍵刪除模型

在上面的例子中,我們在調(diào)用 delete 方法之前從數(shù)據(jù)庫中獲取該模型,不過,如果你知道模型的主鍵的話,可以調(diào)用 destroy 方法直接刪除而不需要獲取它:

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

通過查詢刪除模型

當(dāng)然,你還可以通過查詢刪除多個模型,在本例中,我們刪除所有被標(biāo)記為無效的航班:

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

注:通過 Eloquent 進(jìn)行批量刪除時,deleting 和 deleted 模型事件在刪除模型時不會被觸發(fā),這是因為在進(jìn)行模型刪除時不會獲取模型。

軟刪除

除了從數(shù)據(jù)庫物理刪除記錄外,Eloquent 還可以對模型進(jìn)行“軟刪除”。當(dāng)模型被軟刪除后,它們并沒有真的從數(shù)據(jù)庫刪除,而是在模型上設(shè)置一個 deleted_at 屬性并插入數(shù)據(jù)庫,如果模型有一個非空 deleted_at 值,那么該模型已經(jīng)被軟刪除了。要啟用模型的軟刪除功能,可以使用模型上的Illuminate\Database\Eloquent\SoftDeletes trait 并添加 deleted_at 列到 $dates 屬性:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;

class Flight extends Model
{
 use SoftDeletes;

 /**
  * 應(yīng)該被調(diào)整為日期的屬性
  *
  * @var array
  */
 protected $dates = ['deleted_at'];
}

當(dāng)然,應(yīng)該添加 deleted_at 列到數(shù)據(jù)表。Laravel Schema 構(gòu)建器包含一個輔助函數(shù)來創(chuàng)建該數(shù)據(jù)列:

Schema::table('flights', function ($table) {
 $table->softDeletes();
});

現(xiàn)在,當(dāng)調(diào)用模型的 delete 方法時,deleted_at 列將被設(shè)置為當(dāng)前日期和時間,并且,當(dāng)查詢一個使用軟刪除的模型時,被軟刪除的模型將會自動從查詢結(jié)果中排除。

判斷給定模型實例是否被軟刪除,可以使用 trashed 方法:

if ($flight->trashed()) {
 //
}

查詢被軟刪除的模型

包含軟刪除模型

正如上面提到的,軟刪除模型將會自動從查詢結(jié)果中排除,不過,如果你想要軟刪除模型出現(xiàn)在查詢結(jié)果中,可以使用 withTrashed 方法:

$flights = App\Flight::withTrashed()
   ->where('account_id', 1)
   ->get();

withTrashed 方法也可以用于關(guān)聯(lián)查詢中:

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

只獲取軟刪除模型

onlyTrashed 方法只獲取軟刪除模型:

$flights = App\Flight::onlyTrashed()
   ->where('airline_id', 1)
   ->get();

恢復(fù)軟刪除模型

有時候你希望恢復(fù)一個被軟刪除的模型,可以使用 restore 方法:

$flight->restore();

你還可以在查詢中使用 restore 方法來快速恢復(fù)多個模型,同樣,這也不會觸發(fā)任何模型事件:

App\Flight::withTrashed()
 ->where('airline_id', 1)
 ->restore();

和 withTrashed 方法一樣,restore 方法也可以用于關(guān)聯(lián)查詢:

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

永久刪除模型

有時候你真的需要從數(shù)據(jù)庫中刪除一個模型,要從數(shù)據(jù)庫中永久刪除記錄,可以使用 forceDelete 方法:

// 強制刪除單個模型實例...
$flight->forceDelete();

// 強制刪除所有關(guān)聯(lián)模型...
$flight->history()->forceDelete();

查詢作用域

全局作用域

全局作用域允許我們?yōu)榻o定模型的所有查詢添加條件約束。Laravel 自帶的軟刪除功能就使用了全局作用域來從數(shù)據(jù)庫中拉出所有沒有被刪除的模型。編寫自定義的全局作用域可以提供一種方便的、簡單的方式來確保給定模型的每個查詢都有特定的條件約束。

編寫全局作用域

自定義全局作用域很簡單,首先定義一個實現(xiàn) Illuminate\Database\Eloquent\Scope 接口的類,該接口要求你實現(xiàn)一個方法:apply。需要的話可以在 apply 方法中添加 where 條件到查詢:

<?php

namespace App\Scopes;

use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class AgeScope implements Scope
{
 /**
  * 應(yīng)用作用域到給定的Eloquent查詢構(gòu)建器.
  *
  * @param \Illuminate\Database\Eloquent\Builder $builder
  * @param \Illuminate\Database\Eloquent\Model $model
  * @return void
  * @translator laravelacademy.org
  */
 public function apply(Builder $builder, Model $model)
 {
  return $builder->where('age', '>', 200);
 }
}

Laravel 應(yīng)用默認(rèn)并沒有為作用域預(yù)定義文件夾,所以你可以按照自己的喜好在 app 目錄下創(chuàng)建 Scopes 目錄。

注:如果你的全局作用域需要添加列到查詢的 select 子句,需要使用 addSelect 方法來替代 select,這樣就可以避免已存在的 select 查詢子句造成影響。

應(yīng)用全局作用域

要將全局作用域應(yīng)用到模型,需要重寫給定模型的 boot 方法并使用 addGlobalScope 方法:

<?php

namespace App;

use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;

class User extends Model
{
 /**
  * 模型的“啟動”方法.
  *
  * @return void
  */
 protected static function boot()
 {
  parent::boot();

  static::addGlobalScope(new AgeScope);
 }
}

添加作用域后,如果使用 User::all() 查詢則會生成如下 SQL 語句:

select * from `users` where `age` > 200

匿名的全局作用域

Eloquent 還允許我們使用閉包定義全局作用域,這在實現(xiàn)簡單作用域的時候特別有用,這樣的話,我們就沒必要定義一個單獨的類了:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;

class User extends Model{
 /**
  * The "booting" method of the model.
  *
  * @return void
  */
 protected static function boot()
 {
  parent::boot();

  static::addGlobalScope('age', function(Builder $builder) {
   $builder->where('age', '>', 200);
  });
 }
}

移除全局作用域

如果想要在給定查詢中移除指定全局作用域,可以使用 withoutGlobalScope 方法,該方法接收全局作用域的類名作為其唯一參數(shù):

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

或者,如果你使用閉包定義的全局作用域的話:

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

如果你想要移除某幾個或全部全局作用域,可以使用 withoutGlobalScopes 方法:

// 移除所有全局作用域
User::withoutGlobalScopes()->get();

 //移除某些全局作用域 
 User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();

本地作用域

本地作用域允許我們定義通用的約束集合以便在應(yīng)用中復(fù)用。例如,你可能經(jīng)常需要獲取最受歡迎的用戶,要定義這樣的一個作用域,只需簡單在對應(yīng) Eloquent 模型方法前加上一個 scope 前綴。

作用域總是返回查詢構(gòu)建器實例:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
 /**
  * 只包含活躍用戶的查詢作用域
  *
  * @return \Illuminate\Database\Eloquent\Builder
  */
 public function scopePopular($query)
 {
  return $query->where('votes', '>', 100);
 }

 /**
  * 只包含激活用戶的查詢作用域
  *
  * @return \Illuminate\Database\Eloquent\Builder
  */
 public function scopeActive($query)
 {
  return $query->where('active', 1);
 }
}

使用本地作用域

作用域被定義好了之后,就可以在查詢模型的時候調(diào)用作用域方法,但調(diào)用時不需要加上 scope 前綴,你甚至可以同時調(diào)用多個作用域,例如:

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

動態(tài)作用域

有時候你可能想要定義一個可以接收參數(shù)的作用域,你只需要將額外的參數(shù)添加到你的作用域即可。作用域參數(shù)應(yīng)該被定義在 $query 參數(shù)之后:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class User extends Model
{
 /**
  * 讓查詢只包含給定類型的用戶
  *
  * @param \Illuminate\Database\Eloquent\Builder $query
  * @param mixed $type
  * @return \Illuminate\Database\Eloquent\Builder
  */
 public function scopeOfType($query, $type)
 {
  return $query->where('type', $type);
 }
}

現(xiàn)在,你可以在調(diào)用作用域時傳遞參數(shù)了:

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

比較模型

有時候你可能需要確定兩個模型是否是一樣的,is 方法可用于快速驗證兩個模型是否有相同的主鍵、數(shù)據(jù)表、以及數(shù)據(jù)庫連接:

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

事件

Eloquent 模型可以觸發(fā)事件,允許你在模型生命周期中的多個時間點調(diào)用如下這些方法:retrieved, creating, created, updating, updated, saving, saved, deleting, deleted, restoring, restored。事件允許你在一個指定模型類每次保存或更新的時候執(zhí)行代碼。

retrieved 事件會在從數(shù)據(jù)庫中獲取已存在模型時觸發(fā)。當(dāng)一個新模型被首次保存的時候,creating 和 created 事件會被觸發(fā)。如果一個模型已經(jīng)在數(shù)據(jù)庫中存在并調(diào)用 save 方法,updating/updated 事件會被觸發(fā),無論是創(chuàng)建還是更新,saving/saved 事件都會被觸發(fā)。

注:通過 Eloquent 進(jìn)行批量更新時,模型事件 saved 和 updated 不會在更新模型上觸發(fā),這是因為這些模型在進(jìn)行批量更新時沒有真正檢索過。

舉個例子,在 Eloquent 模型中定義一個 $dispatchesEvents 屬性來映射模型生命周期中多個時間點與對應(yīng)事件類:

<?php

namespace App;

use App\Events\UserSaved;
use App\Events\UserDeleted;
use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;

class User extends Authenticatable
{
 use Notifiable;

 /**
  * The event map for the model.
  *
  * @var array
  */
 protected $dispatchesEvents = [
  'saved' => UserSaved::class,
  'deleted' => UserDeleted::class,
 ];
}

觀察者

定義觀察者

如果你在給定模型中監(jiān)聽多個事件,可以使用觀察者來對所有監(jiān)聽器分組到一個類中,觀察者類擁有反射你想要監(jiān)聽的 Eloquent 事件對應(yīng)的方法名,每個方法接收模型作為唯一參數(shù)。Artisan 命令 make:observer 是創(chuàng)建新的觀察者類的最簡單的方法:

php artisan make:observer UserObserver --model=User

該命令會將新的觀察者生成到 App/Observers 目錄,如果這個目錄不存在,Artisan 會自動創(chuàng)建。剛創(chuàng)建的觀察者類代碼如下:

<?php

namespace App\Observers;

use App\User;

class UserObserver
{
 /**
  * Handle to the User "created" event.
  *
  * @param \App\User $user
  * @return void
  */
 public function created(User $user)
 {
  //
 }

 /**
  * Handle the User "updated" event.
  *
  * @param \App\User $user
  * @return void
  */
 public function updated(User $user)
 {
  //
 }

 /**
  * Handle the User "deleted" event.
  *
  * @param \App\User $user
  * @return void
  */
 public function deleted(User $user)
 {
  //
 }
}

要注冊觀察者,使用你想要觀察模型的 observe 方法,你可以在某個服務(wù)提供者的 boot 方法中注冊觀察者,在本例中,我們在 AppServiceProvider 中注冊觀察者:

<?php

namespace App\Providers;

use App\User;
use App\Observers\UserObserver;
use Illuminate\Support\ServiceProvider;

class AppServiceProvider extends ServiceProvider
{
 /**
  * Bootstrap any application services.
  *
  * @return void
  */
 public function boot()
 {
  User::observe(UserObserver::class);
 }

 /**
  * Register the service provider.
  *
  * @return void
  */
 public function register()
 {
  //
 }
}

以上是“Laravel5.7 Eloquent ORM怎么用”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注億速云行業(yè)資訊頻道!

向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI