Eloquent: 起步
簡(jiǎn)介
Laravel 的 Eloquent ORM 提供了一種漂亮簡(jiǎn)潔的關(guān)系映射的模型來(lái)與數(shù)據(jù)庫(kù)進(jìn)行交互侄榴。所有的數(shù)據(jù)庫(kù)表都有相應(yīng)的模型吠撮,這些模型被用來(lái)與表進(jìn)行交互笆载。模型允許你直接查詢(xún)數(shù)據(jù)庫(kù)表中的數(shù)據(jù)蜈漓,及插入新的記錄到數(shù)據(jù)表中蛹锰。
在開(kāi)始之前粘舟,你需要確保完成了 config/database.php
配置文件中的數(shù)據(jù)庫(kù)配置熔脂。對(duì)于更多的配置數(shù)據(jù)庫(kù)相關(guān)的信息,請(qǐng)參考 文檔柑肴。
定義模型
在開(kāi)始之前霞揉,讓我們先來(lái)創(chuàng)建一個(gè) Eloquent 模型。模型通常存放在 app
目錄下晰骑,但是你也可以自由的放置在任何地方适秩,只要它能夠根據(jù)你的 composer.json
文件的指導(dǎo)進(jìn)行自動(dòng)的加載。所有的 Eloquent 模型都繼承自 Illuminate\Database\Eloquent\Model
類(lèi)硕舆。
最簡(jiǎn)單的創(chuàng)建一個(gè)模型類(lèi)的方式就是使用 make:model
Artisan 命令:
php artisan make:model User
如果你希望在你生成模型的同時(shí)生成一份數(shù)據(jù)庫(kù)遷移秽荞,你可以使用 --migration
或者 -m
選項(xiàng):
php artisan make:model User --migration
php artisan make:model User -m
Eloquent 模型約定
現(xiàn)在,讓我們來(lái)看一個(gè) Flight
模型的示例抚官,我們將通過(guò)它獲取和存儲(chǔ)數(shù)據(jù)庫(kù)中 flights
表的數(shù)據(jù):
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Flight extends Model
{
//
}
表名稱(chēng)
你需要注意我們上面的代碼中并沒(méi)有指出 Flight
模型使用哪個(gè)數(shù)據(jù)庫(kù)的表扬跋。如果你沒(méi)有明確的指出模型所對(duì)應(yīng)的表,那么 Eloquent 將使用類(lèi)的蛇形命名的復(fù)數(shù)形式來(lái)使用相應(yīng)的數(shù)據(jù)表凌节。所以钦听,在這個(gè)例子中,Eloquent 將會(huì)假定 Flight
模型存儲(chǔ)的記錄被放在 flights
表中倍奢。你可以使用 table
屬性來(lái)指定表名:
<?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
屬性來(lái)手動(dòng)的指定表的主鍵。
另外娱挨,Eloquent 也會(huì)假定主鍵是一個(gè)自增的整型值余指,這意味著,在默認(rèn)情況下主鍵會(huì)被自動(dòng)的轉(zhuǎn)為 int
。如果你希望使用非自增或者非數(shù)字的主鍵酵镜,那么你需要在模型中將公開(kāi)的 $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è)屬性用來(lái)決定日期屬性存儲(chǔ)在數(shù)據(jù)庫(kù)中的格式蜡吧,以及模型在進(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ù)庫(kù)連接
默認(rèn)的,所有的 Eloquent 模型都會(huì)使用應(yīng)用配置的默認(rèn)的數(shù)據(jù)庫(kù)連接占键。如果你希望模型使用不同的數(shù)據(jù)庫(kù)連接昔善,你可以使用 $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ù)庫(kù)中檢索數(shù)據(jù)做好了準(zhǔn)備畔乙。你可以把 Eloquent 模型作為一個(gè)強(qiáng)大的查詢(xún)生成器來(lái)使用君仆,它允許通過(guò)模型流暢的查詢(xún)相應(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]);
}
}
訪(fǎng)問(wèn)列的值
如果你獲得了 Eloquent 模型的實(shí)例牲距,那么你可以通過(guò)模型中相應(yīng)的列名的屬性來(lái)訪(fǎng)問(wèn)表中列的值返咱。比如,讓我們循環(huán)查詢(xún)的結(jié)果牍鞠,并通過(guò)獲取的 Flight
實(shí)例來(lái)獲得 name
列的值:
foreach ($flights as $flight) {
echo $flight->name;
}
添加額外的條件
Eloquent 的 all
方法會(huì)返回模型表中所有的記錄咖摹。由于所有的 Eloquent 模型都可以作為查詢(xún)生成器來(lái)進(jìn)行服務(wù),所以你可以在這些查詢(xún)中增加額外的條件难述,然后使用 get
方法來(lái)檢索結(jié)果:
$flights = App\Flight::where('active', 1)
->orderBy('name', 'desc')
->take(10)
->get();
注意:由于 Eloquent 模型也是查詢(xún)生成器萤晴,所以你可以回顧一下查詢(xún)生成器中所有可用的方法,因?yàn)樗鼈兺瑯涌梢栽?Eloquent 中進(jìn)行使用龄广。
集合
對(duì)于像 all
和 get
這樣的 Eloquent 方法會(huì)返回多個(gè)結(jié)果硫眯,這將返回一個(gè) Illuminate\Database\Eloquent\Collection
實(shí)例蕴侧。Collection
類(lèi)提供了各種有用的方法與 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ù)庫(kù)檢索出每塊內(nèi)容時(shí)進(jìn)行調(diào)用敏储。
檢索單個(gè)模型 / 統(tǒng)計(jì)
當(dāng)然阻星,除了可以從表中檢索出所有的記錄之外,你也可以使用 find
和 first
方法來(lái)從數(shù)據(jù)庫(kù)中檢索出單條的數(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í)候滥酥,你可能希望在沒(méi)有找到匹配的模型時(shí)拋出一個(gè)異常。這對(duì)路由或者控制器來(lái)說(shuō)尤其有用畦幢。findOrFail
和 firstOrFail
方法可以從查詢(xún)中檢索出首個(gè)匹配的結(jié)果坎吻,但是,如果結(jié)果中沒(méi)有匹配的項(xiàng)宇葱,那么會(huì)拋出一個(gè) Illuminate\Database\Eloquent\ModelNotFoundException
異常:
$model = App\Flight::findOrFail(1);
$model = App\Flight::where('legs', '>', 100)->firstOrFail();
如果異常沒(méi)有被捕獲瘦真,那么會(huì)直接傳遞給用戶(hù)一個(gè) 404
HTTP 響應(yīng)。所以當(dāng)你在使用這些方法時(shí)是沒(méi)有必要編寫(xiě)明確的檢查并返回 404
響應(yīng)的:
Route::get('/api/flights/{id}', function ($id) {
return App\Flight::findOrFail($id);
});
檢索統(tǒng)計(jì)
當(dāng)然黍瞧,你可以使用 count
诸尽,sum
,max
和其他 查詢(xún)生成器 所提供的的 聚合函數(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ù)庫(kù)中插入新的記錄,只需要簡(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ù)庫(kù)中,同時(shí) created_at
和 updated_at
時(shí)間戳也會(huì)自動(dòng)的被進(jìn)行設(shè)置兴喂,所以這并不需要進(jìn)行手動(dòng)的設(shè)置它們蔼囊。
基礎(chǔ)的更新
save
方法也可用來(lái)更新數(shù)據(jù)庫(kù)中已經(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ì)查詢(xún)匹配的多個(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
方法來(lái)在一行中存儲(chǔ)一個(gè)新的模型陨界。一個(gè)新增的模型實(shí)例將會(huì)從方法中返回巡揍。事實(shí)上,在開(kāi)始做這些之前菌瘪,你需要先指定模型的 fillable
或者 guarded
屬性腮敌,它們是針對(duì)批量賦值時(shí)的保護(hù)措施。
當(dāng)用戶(hù)通過(guò) HTTP 請(qǐng)求傳遞一些意外的參數(shù)時(shí),這可能會(huì)造成批量賦值時(shí)一些問(wèn)題的出現(xiàn)糜工,或許參數(shù)中存在一些你并不想改變的列值的參數(shù)斗这。比如,一個(gè)惡意的用戶(hù)可能會(huì)在請(qǐng)求中嵌入一個(gè) is_admin
參數(shù)啤斗,然后這些參數(shù)映射到你的 create
方法中表箭,這就使用戶(hù)將自己升級(jí)為了超級(jí)管理員。
所以钮莲,在開(kāi)始之前免钻,你需要先定義哪些模型屬性是可以進(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ù)庫(kù)定位相關(guān)的模型突梦。如果相關(guān)的模型沒(méi)有找到诫舅,那么會(huì)根據(jù)給定的屬性在數(shù)據(jù)庫(kù)中新增一條記錄。
firstOrNew
方法和 firstOrCreate
方法一樣宫患,但是它在模型沒(méi)找到時(shí)只會(huì)返回一個(gè)新的模型實(shí)例刊懈,并不會(huì)在數(shù)據(jù)庫(kù)中新增一條記錄。你需要手動(dòng)的使用 save
方法來(lái)將其存儲(chǔ)到數(shù)據(jù)庫(kù)中:
// 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
方法來(lái)刪除模型:
$flight = App\Flight::find(1);
$flight->delete();
根據(jù)鍵刪除存在的模型
在上面的例子中撮奏,我們先從數(shù)據(jù)庫(kù)中檢索出相關(guān)的模型俏讹,然后才調(diào)用 delete
方法來(lái)進(jìn)行刪除当宴。事實(shí)上畜吊,如果你知道了模型的主鍵,那么你完全可以不用去檢索到它户矢。你可以直接使用 destroy
方法來(lái)進(jìn)行刪除:
App\Flight::destroy(1);
App\Flight::destroy([1, 2, 3]);
App\Flight::destroy(1, 2, 3);
通過(guò)查詢(xún)刪除模型
當(dāng)然玲献,你也可以通過(guò)查詢(xún)刪除一個(gè)模型集。在這個(gè)例子中,我們將刪除所有標(biāo)記為未啟用的航班:
$deletedRows = App\Flight::where('active', 0)->delete();
軟刪除
除了從數(shù)據(jù)庫(kù)中真實(shí)的刪除數(shù)據(jù)之外捌年,Eloquent 也可以進(jìn)行軟刪除操作瓢娜。當(dāng)模型是一個(gè)軟刪除模型時(shí),它們并不會(huì)真正的從數(shù)據(jù)庫(kù)中清除記錄礼预。實(shí)際上眠砾,它們會(huì)將模型的 deleted_at
屬性進(jìn)行設(shè)置,并且將其更新到數(shù)據(jù)庫(kù)中托酸。如果模型中的 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)查詢(xún)啟用軟刪除的模型時(shí),已經(jīng)被軟刪除的模型將自動(dòng)從結(jié)果中剔除扮休。
你可以使用 trashed
方法來(lái)判斷所給定的模型是否已經(jīng)被軟刪除:
if ($flight->trashed()) {
//
}
查詢(xún)軟刪除的模型
包含軟刪除的模型
就如上面我們所提到的漩绵,被軟刪除的模型將自動(dòng)的從結(jié)果中進(jìn)行剔除。事實(shí)上肛炮,你可以使用 withTrashed
方法來(lái)強(qiáng)制結(jié)果中顯示已經(jīng)被軟刪除的模型:
$flights = App\Flight::withTrashed()
->where('account_id', 1)
->get();
whitTrashed
方法也可以在關(guān)聯(lián)查詢(xún)中進(jìn)行使用:
$flight->history()->withTrashed()->get();
只檢索被軟刪除的模型
onlyTrashed
方法會(huì)從數(shù)據(jù)庫(kù)中檢索被軟刪除的模型記錄:
$flights = App\Flight::onlyTrashed()
->where('airline_id', 1)
->get();
還原被軟刪除的模型
有時(shí)候你可能會(huì)希望還原已經(jīng)被軟刪除的模型止吐,你可以使用 restore
方法來(lái)將模型從軟刪除中解除:
$flight->restore();
你也可以在查詢(xún)中使用 restore
方法來(lái)快速的重啟多個(gè)模型:
App\Flight::withTrashed()
->where('airline_id', 1)
->restore();
就像 withTrashed
方法一樣,restore
方法也可以在關(guān)聯(lián)查詢(xún)中使用:
$flight->history()->restore();
永久的刪除模型
有時(shí)候你可能希望從數(shù)據(jù)庫(kù)中直接刪除這個(gè)模型侨糟。你可以使用 forceDelete
方法來(lái)將模型從數(shù)據(jù)庫(kù)中永久的刪除:
// Force deleting a single model instance...
$flight->forceDelete();
// Force deleting all related modls...
$flight->history()->forceDelete();
查詢(xún)區(qū)間
全局區(qū)間
全局區(qū)間允許你在給定的模型上的所有查詢(xún)進(jìn)行約束的添加碍扔。Laravel 自己的軟刪除功能就是利用了全局區(qū)間來(lái)從數(shù)據(jù)庫(kù)中拉取未刪除的數(shù)據(jù)。編寫(xiě)自己的全局區(qū)間可以方便的對(duì)給定模型的所有查詢(xún)進(jìn)行約束秕重。
編寫(xiě)全局區(qū)間
編寫(xiě)一個(gè)全局區(qū)間非常簡(jiǎn)單不同,你只需要定義一個(gè)實(shí)現(xiàn)了 Illuminate\Database\Eloquent\Scope
接口的類(lèi)。這個(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 沒(méi)有為區(qū)間預(yù)置存放的目錄二拐,所以你可以自由的創(chuàng)建自己的 Scopes
目錄來(lái)進(jìn)行管理。
應(yīng)用全局區(qū)間
你需要在給定的模型中復(fù)寫(xiě) boot
方法并且使用 addGlobalScope
方法來(lái)分配全局區(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()
的查詢(xún)會(huì)產(chǎn)生下述的 SQL:
select * from `users` where `age` > 200
匿名全局區(qū)間
Eloquent 也允許你通過(guò)一個(gè)閉包來(lái)定義全局區(qū)間百新,這通常對(duì)于不需要分離到單獨(dú)一個(gè)類(lèi)文件中的簡(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í),你可以通過(guò)標(biāo)識(shí)將其排除:
User::withoutGlobalScope('age')->get();
刪除全局區(qū)間
如果你希望從給定的查詢(xún)中移除全局區(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)常需要檢索一些受歡迎的用戶(hù)铅辞。你可以簡(jiǎn)單的在模型方法中前置 scope
命名來(lái)定義一個(gè)區(qū)間.
區(qū)間應(yīng)該總是返回一個(gè)查詢(xún)生成器的實(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ū)間查詢(xún)
一旦區(qū)間進(jìn)行了定義厌漂,你可以在模型進(jìn)行查詢(xú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ū)間。在開(kāi)始之前囤踩,你僅僅只需要在你的區(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ù)庫(kù)中遗锣,并且調(diào)用 save
方法货裹,那么 updating
/ updated
事件將會(huì)被觸發(fā)。事實(shí)上精偿,在這兩種情況下弧圆,saving
和 saved
事件都會(huì)被觸發(fā)。
舉個(gè)示例笔咽,讓我們?cè)诜?wù)提供者中定義一個(gè) Eloquent 事件監(jiān)聽(tīng)器搔预。在我們的事件監(jiān)聽(tīng)器中,我們將在給定的模型中調(diào)用 isValid
方法叶组,當(dāng)模型并沒(méi)有通過(guò)驗(yàn)證時(shí)將返回 false
拯田。如果從 Eloquent 事件監(jiān)聽(tīng)器中返回 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()
{
//
}
}