Eloquent: 起步
簡(jiǎn)介
Laravel 的 Eloquent ORM 提供了一種漂亮簡(jiǎn)潔的關(guān)系映射的模型來與數(shù)據(jù)庫進(jìn)行交互。所有的數(shù)據(jù)庫表都有相應(yīng)的模型,這些模型被用來與表進(jìn)行交互。模型允許你直接查詢數(shù)據(jù)庫表中的數(shù)據(jù),及插入新的記錄到數(shù)據(jù)表中。
在開始之前,你需要確保完成了 config/database.php 配置文件中的數(shù)據(jù)庫配置。對(duì)于更多的配置數(shù)據(jù)庫相關(guān)的信息,請(qǐng)參考 文檔。
定義模型
在開始之前,讓我們先來創(chuàng)建一個(gè) Eloquent 模型。模型通常存放在 app 目錄下,但是你也可以自由的放置在任何地方,只要它能夠根據(jù)你的 composer.json 文件的指導(dǎo)進(jìn)行自動(dòng)的加載。所有的 Eloquent 模型都繼承自 Illuminate\Database\Eloquent\Model 類。
最簡(jiǎn)單的創(chuàng)建一個(gè)模型類的方式就是使用 make:model Artisan 命令:
php artisan make:model User
如果你希望在你生成模型的同時(shí)生成一份數(shù)據(jù)庫遷移,你可以使用 --migration 或者 -m 選項(xiàng):
php artisan make:model User --migration
php artisan make:model User -m
Eloquent 模型約定
現(xiàn)在,讓我們來看一個(gè) Flight 模型的示例,我們將通過它獲取和存儲(chǔ)數(shù)據(jù)庫中 flights 表的數(shù)據(jù):
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
//
}
表名稱
你需要注意我們上面的代碼中并沒有指出 Flight 模型使用哪個(gè)數(shù)據(jù)庫的表。如果你沒有明確的指出模型所對(duì)應(yīng)的表,那么 Eloquent 將使用類的蛇形命名的復(fù)數(shù)形式來使用相應(yīng)的數(shù)據(jù)表。所以,在這個(gè)例子中,Eloquent 將會(huì)假定 Flight 模型存儲(chǔ)的記錄被放在 flights 表中。你可以使用 table 屬性來指定表名:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'my_flights';
}
主鍵
Eloquent 也會(huì)假定所有表的主鍵列名為 id。你也可使用 $primaryKey 屬性來手動(dòng)的指定表的主鍵。
另外,Eloquent 也會(huì)假定主鍵是一個(gè)自增的整型值,這意味著,在默認(rèn)情況下主鍵會(huì)被自動(dòng)的轉(zhuǎn)為 int。如果你希望使用非自增或者非數(shù)字的主鍵,那么你需要在模型中將公開的 $incrementing 屬性設(shè)置為 false。
時(shí)間戳
默認(rèn)的,Eloquent 期望模型表中存在 created_at 和 updated_at 列,如果你不希望 Eloquent 自主的管理這兩列,你可以在模型中設(shè)置 $timestamps 屬性為 false:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* Indicates if the model should be timestamped.
*
* @var bool
*/
public $timestamps = false;
}
如果你需要自定義時(shí)間戳的格式,你可以設(shè)置 $dateFormat 屬性。這個(gè)屬性用來決定日期屬性存儲(chǔ)在數(shù)據(jù)庫中的格式,以及模型在進(jìn)行序列化為數(shù)組或者 JSON 時(shí)的顯示樣式:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The storage format of the model's date columns.
*
* @var string
*/
protected $dateFormat = 'U';
}
數(shù)據(jù)庫連接
默認(rèn)的,所有的 Eloquent 模型都會(huì)使用應(yīng)用配置的默認(rèn)的數(shù)據(jù)庫連接。如果你希望模型使用不同的數(shù)據(jù)庫連接,你可以使用 $connection 屬性:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The connection name for the model.
*
* @var string
*/
protected $connection = 'connection-name';
}
檢索多個(gè)模型
一旦你創(chuàng)建了模型和其相應(yīng)的數(shù)據(jù)表,你就為從數(shù)據(jù)庫中檢索數(shù)據(jù)做好了準(zhǔn)備。你可以把 Eloquent 模型作為一個(gè)強(qiáng)大的查詢生成器來使用,它允許通過模型流暢的查詢相應(yīng)的表中的數(shù)據(jù)。比如:
<?php
namespace App\Http\Controllers;
use App\Flight;
use App\Http\Controllers\Controller;
class FlightController extends Controller
{
/**
* Show a list of all available flights.
*
* @return Response
*/
public function index()
{
$flights = Flight::all();
return view('flight.index', ['flights' => $flights]);
}
}
訪問列的值
如果你獲得了 Eloquent 模型的實(shí)例,那么你可以通過模型中相應(yīng)的列名的屬性來訪問表中列的值。比如,讓我們循環(huán)查詢的結(jié)果,并通過獲取的 Flight 實(shí)例來獲得 name 列的值:
foreach ($flights as $flight) {
echo $flight->name;
}
添加額外的條件
Eloquent 的 all 方法會(huì)返回模型表中所有的記錄。由于所有的 Eloquent 模型都可以作為查詢生成器來進(jìn)行服務(wù),所以你可以在這些查詢中增加額外的條件,然后使用 get 方法來檢索結(jié)果:
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
注意:由于 Eloquent 模型也是查詢生成器,所以你可以回顧一下查詢生成器中所有可用的方法,因?yàn)樗鼈兺瑯涌梢栽?Eloquent 中進(jìn)行使用。
集合
對(duì)于像 all 和 get 這樣的 Eloquent 方法會(huì)返回多個(gè)結(jié)果,這將返回一個(gè) Illuminate\Database\Eloquent\Collection 實(shí)例。Collection 類提供了各種有用的方法與 Eloquent 結(jié)果進(jìn)行交互。當(dāng)然,你可以簡(jiǎn)單的對(duì)集合進(jìn)行循環(huán),因?yàn)樗麑?shí)現(xiàn)了 ArrayAccess 接口:
foreach ($flights as $flight) {
echo $flight->name;
}
對(duì)結(jié)果進(jìn)行分塊
如果你需要處理數(shù)千條 Eloquent 記錄,那么你可以使用 chunk 方法。chunk 方法會(huì)從 Eloquent 模型中檢索出一小塊記錄,然后將其傳遞給 Closure 進(jìn)行處理。使用 chunk 方法在處理大量結(jié)果集時(shí)可有有效的降低內(nèi)存的消耗:
Flight::chunk(200, function ($flights) {
foreach ($flights as $flight) {
//
}
});
傳遞到方法的第一個(gè)參數(shù)是你要設(shè)置進(jìn)行分塊的大小。而傳遞到第二個(gè)參數(shù)的閉包將會(huì)在從數(shù)據(jù)庫檢索出每塊內(nèi)容時(shí)進(jìn)行調(diào)用。
檢索單個(gè)模型 / 統(tǒng)計(jì)
當(dāng)然,除了可以從表中檢索出所有的記錄之外,你也可以使用 find 和 first 方法來從數(shù)據(jù)庫中檢索出單條的數(shù)據(jù)。這將會(huì)返回一個(gè)單獨(dú)的模型實(shí)例:
// Retrieve a model by its primary key...
$flight = App\Flight::find(1);
// Retrieve the first model matching the query constraints...
$flight = App\Flight::where('active', 1)->first();
你也可以使用 find 方法時(shí)傳遞一個(gè)包含主鍵所組成的數(shù)組,這將返回所有匹配到記錄的集合:
$flights = App\Flight::find([1, 2, 3]);
未發(fā)現(xiàn)時(shí)的異常
有時(shí)候,你可能希望在沒有找到匹配的模型時(shí)拋出一個(gè)異常。這對(duì)路由或者控制器來說尤其有用。findOrFail 和 firstOrFail 方法可以從查詢中檢索出首個(gè)匹配的結(jié)果,但是,如果結(jié)果中沒有匹配的項(xiàng),那么會(huì)拋出一個(gè) Illuminate\Database\Eloquent\ModelNotFoundException 異常:
$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();
如果異常沒有被捕獲,那么會(huì)直接傳遞給用戶一個(gè) 404 HTTP 響應(yīng)。所以當(dāng)你在使用這些方法時(shí)是沒有必要編寫明確的檢查并返回 404 響應(yīng)的:
Route::get('/api/flights/{id}', function ($id) {
return App\Flight::findOrFail($id);
});
檢索統(tǒng)計(jì)
當(dāng)然,你可以使用 count,sum,max 和其他 查詢生成器 所提供的的 聚合函數(shù)。這些方法會(huì)返回適當(dāng)?shù)臄?shù)值,而不是完整的模型實(shí)例:
$count = App\Flight::where('active', 1)->count();
$max = App\Flight::where('active', 1)->max('price');
插入 & 更新模型
基礎(chǔ)插入
想要在數(shù)據(jù)庫中插入新的記錄,只需要簡(jiǎn)單的創(chuàng)建模型實(shí)例,然后設(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
{
/**
* Create a new flight instance.
*
* @param Request $request
* @return Response
*/
public function store(Request $request)
{
// Validate the request...
$flight = new Flight;
$flight->name = $request->name;
$flight->save();
}
}
在這個(gè)例子中,我們簡(jiǎn)單的從流入的 HTTP 請(qǐng)求中的 name 參數(shù)分配到 App\Flight 模型實(shí)例的 name 屬性上。當(dāng)我們調(diào)用 save 方法時(shí),這條記錄將會(huì)插入到數(shù)據(jù)庫中,同時(shí) created_at 和 updated_at 時(shí)間戳也會(huì)自動(dòng)的被進(jìn)行設(shè)置,所以這并不需要進(jìn)行手動(dòng)的設(shè)置它們。
基礎(chǔ)的更新
save 方法也可用來更新數(shù)據(jù)庫中已經(jīng)存在的數(shù)據(jù)模型。為了更新模型,你應(yīng)該首先檢索到它們,然后設(shè)置任何你想要更新的屬性,接著調(diào)用 save 方法。這一次,updated_at 時(shí)間戳?xí)詣?dòng)的進(jìn)行更新,所以你并不需要手動(dòng)的更新這個(gè)值:
$flight = App\Flight::find(1);
$flight->name = 'New Flight Name';
$flight->save();
你也可以針對(duì)查詢匹配的多個(gè)模型進(jìn)行更新操作。比如,所有 active 并且 destination 為 San Diego 的航班將會(huì)被標(biāo)記為延遲:
App\Flight::where('active', 1)
->where('destination', 'San Diego')
->update(['delayed' => 1]);
update 方法接收一個(gè)想要更新的列的鍵值對(duì)數(shù)組。
批量賦值
你也可以使用 create 方法來在一行中存儲(chǔ)一個(gè)新的模型。一個(gè)新增的模型實(shí)例將會(huì)從方法中返回。事實(shí)上,在開始做這些之前,你需要先指定模型的 fillable 或者 guarded 屬性,它們是針對(duì)批量賦值時(shí)的保護(hù)措施。
當(dāng)用戶通過 HTTP 請(qǐng)求傳遞一些意外的參數(shù)時(shí),這可能會(huì)造成批量賦值時(shí)一些問題的出現(xiàn),或許參數(shù)中存在一些你并不想改變的列值的參數(shù)。比如,一個(gè)惡意的用戶可能會(huì)在請(qǐng)求中嵌入一個(gè) is_admin 參數(shù),然后這些參數(shù)映射到你的 create 方法中,這就使用戶將自己升級(jí)為了超級(jí)管理員。
所以,在開始之前,你需要先定義哪些模型屬性是可以進(jìn)行批量分配的。你可以使用模型 $fillable 屬性,讓我們?cè)?Flight 模型中添加允許 name 屬性的批量賦值:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Dlight extends Model
{
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = ['name'];
}
一旦我們使一個(gè)屬性可以進(jìn)行批量賦值。那么我們可以使用 create 方法直接的添加記錄到數(shù)據(jù)中。create 方法會(huì)返回存儲(chǔ)后的模型實(shí)例:
$flight = App\Flight::create(['name' => 'Flight 10']);
而 $fillable 就像是為批量賦值提供了一種白名單的機(jī)制。你也可以選擇使用 $guarded。$guarded 屬性應(yīng)該包含一個(gè)你不想要進(jìn)行批量賦值的屬性所組成的數(shù)組。所有不在這個(gè)數(shù)組中的屬性都將可以進(jìn)行批量賦值。所以,$guarded 就像一個(gè)黑名單的功能。當(dāng)然,你應(yīng)該只使用 $fillable 或者 $guarded 中的一個(gè),而不是全部:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
/**
* The attributes that aren't mass assignable.
*
* @var array
*/
protected $guarded = ['price'];
}
在上面的例子中,除了 price,所有的屬性都可以進(jìn)行批量賦值。
其他創(chuàng)建方法
這里也有其他兩種方法可以使用批量賦值進(jìn)行模型的創(chuàng)建:firstOrCreate 和 firstOrNew。firstOrCreate 方法會(huì)嘗試根據(jù)給定的列的鍵值對(duì)從數(shù)據(jù)庫定位相關(guān)的模型。如果相關(guān)的模型沒有找到,那么會(huì)根據(jù)給定的屬性在數(shù)據(jù)庫中新增一條記錄。
firstOrNew 方法和 firstOrCreate 方法一樣,但是它在模型沒找到時(shí)只會(huì)返回一個(gè)新的模型實(shí)例,并不會(huì)在數(shù)據(jù)庫中新增一條記錄。你需要手動(dòng)的使用 save 方法來將其存儲(chǔ)到數(shù)據(jù)庫中:
// Retrieve the flight by the attributes, or create it if it doesn't exists...
$flight = App\Flight::firstOrCreate(['name' => 'Flight 10']);
// Retrieve the flight by the attributes, or instantiate a new instance...
$flight = App\Flight::firstOrNew(['name' => 'Flight 10']);
刪除模型
你可以在模型實(shí)例中使用 delete 方法來刪除模型:
$flight = App\Flight::find(1);
$flight->delete();
根據(jù)鍵刪除存在的模型
在上面的例子中,我們先從數(shù)據(jù)庫中檢索出相關(guān)的模型,然后才調(diào)用 delete 方法來進(jìn)行刪除。事實(shí)上,如果你知道了模型的主鍵,那么你完全可以不用去檢索到它。你可以直接使用 destroy 方法來進(jìn)行刪除:
App\Flight::destroy(1);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(1, 2, 3);
通過查詢刪除模型
當(dāng)然,你也可以通過查詢刪除一個(gè)模型集。在這個(gè)例子中,我們將刪除所有標(biāo)記為未啟用的航班:
$deletedRows = App\Flight::where('active', 0)->delete();
軟刪除
除了從數(shù)據(jù)庫中真實(shí)的刪除數(shù)據(jù)之外,Eloquent 也可以進(jìn)行軟刪除操作。當(dāng)模型是一個(gè)軟刪除模型時(shí),它們并不會(huì)真正的從數(shù)據(jù)庫中清除記錄。實(shí)際上,它們會(huì)將模型的 deleted_at 屬性進(jìn)行設(shè)置,并且將其更新到數(shù)據(jù)庫中。如果模型中的 deleted_at 的值不是 NULL,那么它就被標(biāo)記為軟刪除了。如果你需要啟用軟刪除模型,你需要在模型中引入 Illuminate\Database\Eloquent\SoftDeletes trait,并且在模型的 $dates 屬性中添加 deleted_at 列:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
class Flight extends Model
{
use SoftDeletes;
/**
* The attributes that should be mutated to dates.
*
* @var array
*/
protected $dates = ['deleted_at'];
}
當(dāng)然,你應(yīng)該在數(shù)據(jù)表中添加 deleted_at 列。Laravel 的 結(jié)構(gòu)生成器 中提供了生成該列的方法:
Schema::table('flights', function ($table) {
$table->softDeletes();
});
現(xiàn)在,當(dāng)我們調(diào)用 delete 方法時(shí),deleted_at 列會(huì)被設(shè)置為當(dāng)前時(shí)間。并且,當(dāng)查詢啟用軟刪除的模型時(shí),已經(jīng)被軟刪除的模型將自動(dòng)從結(jié)果中剔除。
你可以使用 trashed 方法來判斷所給定的模型是否已經(jīng)被軟刪除:
if ($flight->trashed()) {
//
}
查詢軟刪除的模型
包含軟刪除的模型
就如上面我們所提到的,被軟刪除的模型將自動(dòng)的從結(jié)果中進(jìn)行剔除。事實(shí)上,你可以使用 withTrashed 方法來強(qiáng)制結(jié)果中顯示已經(jīng)被軟刪除的模型:
$flights = App\Flight::withTrashed()
->where('account_id', 1)
->get();
whitTrashed 方法也可以在關(guān)聯(lián)查詢中進(jìn)行使用:
$flight->history()->withTrashed()->get();
只檢索被軟刪除的模型
onlyTrashed 方法會(huì)從數(shù)據(jù)庫中檢索被軟刪除的模型記錄:
$flights = App\Flight::onlyTrashed()
->where('airline_id', 1)
->get();
還原被軟刪除的模型
有時(shí)候你可能會(huì)希望還原已經(jīng)被軟刪除的模型,你可以使用 restore 方法來將模型從軟刪除中解除:
$flight->restore();
你也可以在查詢中使用 restore 方法來快速的重啟多個(gè)模型:
App\Flight::withTrashed()
->where('airline_id', 1)
->restore();
就像 withTrashed 方法一樣,restore 方法也可以在關(guān)聯(lián)查詢中使用:
$flight->history()->restore();
永久的刪除模型
有時(shí)候你可能希望從數(shù)據(jù)庫中直接刪除這個(gè)模型。你可以使用 forceDelete 方法來將模型從數(shù)據(jù)庫中永久的刪除:
// Force deleting a single model instance...
$flight->forceDelete();
// Force deleting all related modls...
$flight->history()->forceDelete();
查詢區(qū)間
全局區(qū)間
全局區(qū)間允許你在給定的模型上的所有查詢進(jìn)行約束的添加。Laravel 自己的軟刪除功能就是利用了全局區(qū)間來從數(shù)據(jù)庫中拉取未刪除的數(shù)據(jù)。編寫自己的全局區(qū)間可以方便的對(duì)給定模型的所有查詢進(jìn)行約束。
編寫全局區(qū)間
編寫一個(gè)全局區(qū)間非常簡(jiǎn)單,你只需要定義一個(gè)實(shí)現(xiàn)了 Illuminate\Database\Eloquent\Scope 接口的類。這個(gè)接口只要求你實(shí)現(xiàn)一個(gè)方法:apply。apply 方法可以在需要的時(shí)添加 where 約束:
<?Php
namespace App\Scopes;
use Illuminate\Database\Eloquent\Scope;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Builder;
class AgeScope implements Scope
{
/**
* Apply the scope to a given Eloquent query builder.
*
* @param \Illuminate\Database\Eloquent\Builder $builder
* @param \Illuminate\Database\Eloquent\Model $model
* @return void
*/
public function apply(Builder $builder, Model $model)
{
return $builder->where('age', '>', 200);
}
}
Laravel 沒有為區(qū)間預(yù)置存放的目錄,所以你可以自由的創(chuàng)建自己的 Scopes 目錄來進(jìn)行管理。
應(yīng)用全局區(qū)間
你需要在給定的模型中復(fù)寫 boot 方法并且使用 addGlobalScope 方法來分配全局區(qū)間:
<?php
namespace App;
use App\Scopes\AgeScope;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* The "booting" method of the model
*
* @return void
*/
protected static function boot()
{
paraent::boot();
static::addGlobalScope(new AgeScope);
}
}
在添加完區(qū)間之后,調(diào)用 User::all() 的查詢會(huì)產(chǎn)生下述的 SQL:
select * from `users` where `age` > 200
匿名全局區(qū)間
Eloquent 也允許你通過一個(gè)閉包來定義全局區(qū)間,這通常對(duì)于不需要分離到單獨(dú)一個(gè)類文件中的簡(jiǎn)單區(qū)間尤其有用:
<?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);
});
}
}
傳遞到 addGlobalScope() 方法的首個(gè)參數(shù)將作為區(qū)間的唯一標(biāo)識(shí),你可以通過標(biāo)識(shí)將其排除:
User::withoutGlobalScope('age')->get();
刪除全局區(qū)間
如果你希望從給定的查詢中移除全局區(qū)間,你可以使用 withoutGlobalScope 方法:
User::withoutGlobalScope(AgeScope::class)->get();
如果你希望刪除多個(gè)或者全部的全局區(qū)間,你可以使用這么使用 withoutGlobalScopes 方法:
User::withoutGlobalScopes()->get();
User::withoutGlobalScopes([FirstScope::class, SecondScope::class])->get();
當(dāng)前區(qū)間
當(dāng)前區(qū)間允許你在模型中定義一些可以復(fù)用的常用的約束。比如,你可能經(jīng)常需要檢索一些受歡迎的用戶。你可以簡(jiǎn)單的在模型方法中前置 scope 命名來定義一個(gè)區(qū)間.
區(qū)間應(yīng)該總是返回一個(gè)查詢生成器的實(shí)例:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Scope a query to only include popular users.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
/**
* Scope a query to only include active users.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopePopular($query)
{
return $query->where('votes', '>', 100);
}
/**
* Scope a query to only include active users.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive($query)
{
return $query->where('active', 1);
}
}
利用區(qū)間查詢
一旦區(qū)間進(jìn)行了定義,你可以在模型進(jìn)行查詢時(shí)調(diào)用區(qū)間方法,事實(shí)上,你在調(diào)用區(qū)間方法時(shí)并不需要包含 scope 前綴。你甚至可以鏈?zhǔn)降恼{(diào)用其它的區(qū)間:
$users = App\User::popular()->active()->orderBy('created_at')->get();
動(dòng)態(tài)區(qū)間
有時(shí)候你可能希望定義一個(gè)可以接收參數(shù)的區(qū)間。在開始之前,你僅僅只需要在你的區(qū)間中添加一些額外的參數(shù)。區(qū)間參數(shù)應(yīng)該在 $query 參數(shù)之后進(jìn)行定義:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* Scope a query to only include users of a given type.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeOfType($query, $type)
{
return $query->where('type', $type);
}
}
現(xiàn)在,你可以在調(diào)用區(qū)間時(shí)傳遞一些參數(shù)了:
$users = App\User::ofType('admin')->get();
事件
Eloquent 模型可以觸發(fā)多種事件,這允許你在模型的生命周期的各個(gè)關(guān)鍵點(diǎn)進(jìn)行 hook 操作。你可以使用下面的方法進(jìn)行 Hook:creating,created,updating,updated,saving,saved,deleting,deleted,restoring,restored。事件允許你輕松的在模型進(jìn)行存儲(chǔ)或更新操作時(shí)進(jìn)行執(zhí)行額外的操作。
基礎(chǔ)用法
當(dāng)一個(gè)新的模型首次進(jìn)行存儲(chǔ)操作時(shí),會(huì)觸發(fā) creating 和 created 事件。如果模型已經(jīng)存在于數(shù)據(jù)庫中,并且調(diào)用 save 方法,那么 updating / updated 事件將會(huì)被觸發(fā)。事實(shí)上,在這兩種情況下,saving 和 saved 事件都會(huì)被觸發(fā)。
舉個(gè)示例,讓我們?cè)诜?wù)提供者中定義一個(gè) Eloquent 事件監(jiān)聽器。在我們的事件監(jiān)聽器中,我們將在給定的模型中調(diào)用 isValid 方法,當(dāng)模型并沒有通過驗(yàn)證時(shí)將返回 false。如果從 Eloquent 事件監(jiān)聽器中返回 false,那么將取消 save / update 操作:
<?php
namespace App\Providers;
use App\User;
use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider
{
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
User::creating(function ($user) {
if (! $user->isValid()) {
return false;
}
});
}
/**
* Register the service provider.
*
* @return void
*/
public function register()
{
//
}
}