翻譯自:aschmelyun.com/blog/5-tips-for-sup...
在過去的五年左右的時間裡,我一直在與Laravel合作,在那段時間裡,我遇到了一些案例,在這些案例中,我需要一種獨特或非典型的方式來從應用程式中返回資料。使用Eloquent
提取資料變得容易,但是仍然有一些用例需要我進行一些挖掘和理解,以弄清楚如何做自己想完成的事情。
我在下面列出了其中的五個,以及程式碼示例和為每個示例返回的偽資料。
準備好? 讓我們開始吧!
有條件地建立查詢
假設我們有一個 Property 模型,其中包含 價格列以及是否允許您養寵物。當使用者訪問時,我們希望過濾掉資料example.com/properties?rent=1200&pets=true
。
public function test(Request $request)
{
if ($request->get('rent') && $request->get('pets')) {
return Property::where('rent', <=, $request->get('rent'))->where('pets_allowed', true))->get();
}
if ($request->get('rent')) {
return Property::where('rent', <=, $request->get('rent'))->get();
}
if ($request->get('pets')) {
return Property::where('pets_allowed', true))->get();
}
return Property::all();
}
我們可以建立一個查詢,然後根據這些條件(而不是依賴它們)新增到查詢中。
使用Model::query()
,然後我們可以根據存在的過濾器連結到 where
語句上。
最後呼叫get
返回我們的資料:
public function test(Request $request)
{
$properties = Property::query();
if ($request->get('rent')) {
$properties->where('rent', <=, $request->get('rent'));
}
if ($request->get('pets')) {
$properties->where('pets_allowed', true));
}
return $properties->get();
}
這樣可以確保每個過濾器僅需要一個條件語句,並且可以將過濾器組合自動連結到此查詢。
返回最新關係
以我們之前的 Property 模型為例,假設有多個與 Tenant 模型相關聯的 租戶 模型。要拉入所有帶有其附加租戶的屬性,您可能會使用類似以下內容的方法:
public function test(Request $request)
{
return Property::with('tenants')->get();
}
但是,如果您只想返回一位租戶,該怎麼辦?
public function tenants()
{
return $this->hasMany(Tenant::class);
}
public function newestTenant()
{
return $this->hasOne(Tenant::class)->orderBy('lease_expires_at', 'desc');
}
現在,如果我們回到以前的測試方法並將其修改為用 Property::with('newestTenant')
,我們將只得到一個租戶。
按巢狀值過濾專案
使用我們之前的財產和租戶模型以及關係,如果只想返回那些租戶沒有狗或貓的財產,該怎麼辦?您可能可以使用類似以下的內容:
public function test(Request $request)
{
return Property::with(['tenants' => function($query) {
$query->where('has_dogs', false)->where('has_cats', false);
}])->get();
}
但我想做的是過濾掉這些屬性,然後只返回那些包含那些過濾後的關係的屬性。我們可以在物件上執行一個foreach迴圈並檢查該空的租戶陣列,或者可以使用Eloquent的whereHas()
方法:
public function test(Request $request) {
return Property::whereHas('tenants', function($query) {
$query->where('has_dogs', false)->where('has_cats', false);
})->with(['tenants' => function($query) {
$query->where('has_dogs', false)->where('has_cats', false);
}])->get();
}
通過使用whereHas()
,上面的方法僅返回與作為第一個引數輸入的列匹配的那些屬性。我們的第二個引數基於連結到查詢物件的方法過濾該列。
然後,我們通過將這些租戶附加到返回的屬性中來進行後續操作,並獲得結果。
生成和插入動態屬性
我們假設有兩個新模型:Technicians和Requests。技術人員與其他技術人員共享多個請求。如果我們希望有一種方法可以一眼就能輕鬆地看到我們的資料,那麼每個技術人員物件有多少個請求呢?我們可以將它們每個都作為延遲載入包含進來,然後獲取陣列的長度,或者我們可以建立一個動態屬性來計算並儲存該值。
首先,我們必須在Technician模型新增以下方法:
public function getRequestsCountAttribute()
{
return $this->requests()->count();
}
在Laravel中,動態屬性的命名約定:
- 使用camelCase
- 以
get
開始 - 包含您想要的下一個列名稱
- 結束於
Attribute
因此,以上方法將在我們返回的技術人員上建立一個動態列,稱為requests_count
,該列將包含附加至模型的已連線請求的數量。
輕鬆過濾日期
關於第五個也是最後一個技巧,讓我們回到租戶模型。正如我們前面提到的,每個人的租約到期時都有一列要儲存。好吧,如果我們只想返回那些在2021年7月到期的使用者,該怎麼辦?
我們也許可以做類似的事情:
public function test(Request $request)
{
return Tenant::where('lease_expires_at', 'LIKE', '2021-07-%')->get();
}
那將完美地工作,並且只返回我們想要的租戶。但是我並不熱衷於LIKE
在不需要的地方使用語句。它們可能會變得凌亂,Laravel為我們提供了兩種更好的方法:
public function test(Request $request)
{
return Tenant::whereMonth('lease_expires_at', '07')->whereYear('lease_expires_at', '2021)->get();
}
使用whereMonth
和whereYear
,我們只能過濾那些租約在2021年7月到期的模型。如果我們想提供一些動態過濾功能,我們甚至可以將那些硬編碼的值替換為,$request->get('month')
或者$request->get('year')
則可以替換。
目前為止就這樣了!
這是五個簡單但功能強大的方法和組織技巧,可用於Laravel的Eloquent ORM來提高生產力。此外,這可能有助於您開始思考如何優化查詢並減少整體程式碼混亂。
本作品採用《CC 協議》,轉載必須註明作者和本文連結