[英]Eager load relationship with parameter in Laravel
在我的 Laravel 應用程序中,我希望有一個關系有條件地從兩個表之一加載數據,具體取決於指定的參數。
我有兩個具有相同列的數據透視表,稱為driver_route
和driver_route_history
。 它們都關聯driver_id
和route_id
列。 唯一的區別是driver_route_history
有一個date
列,其中包含一個絕對的時間日期(例如 06/08/2022),而driver_route
有一個weekday
列,它指的是當前周。
driver_route
中的記錄可由用戶修改。 在每周結束時,它們被克隆到driver_route_history
,這樣每周的變化都會被保存下來。
我希望能夠提取一天的數據。 如果指定日期在當前周內或引用未來日期,則應從driver_route
加載數據。 如果日期早於本周開始,則應從driver_route_history
中提取數據。
我有一個可以做到這一點的函數,當通常從應用程序內的某個地方作為函數調用時:
public function driversOnDay($date)
{
$carbon_date = Carbon::parse($date);
if ($carbon_date->isBefore(Carbon::today()->startOfWeek())) {
return $this->belongsToMany(Driver::class, 'driver_route_history')->wherePivot('date', $carbon_date);
} else {
return $this->belongsToMany(Driver::class, 'driver_route')->wherePivot('weekday', strtolower($carbon_date->shortDayName));
}
}
我想使用 Laravel 的熱切加載在每個 Route 記錄上加載這個關系,如下所示:
Route::with(['driversOnDay' => function($query) { ... });
如何將driversOnDay
date
參數包含在這個急切的加載調用中?
據我了解,模型Route通過多對多關系與Driver模型相關聯,如果 $date 在本周或將來, driver_route_history
需要通過driver_route
數據透視表加入關系,如果$date
$date
,則需要通過 driver_route_history 數據透視表加入關系早於本周開始。
一種方法是在模型上定義兩個獨立的關系,然后使用范圍:
class Route extends Model
{
public function driversOnDay()
{
return $this->belongsToMany(Driver::class, 'driver_route');
}
public function driversOnDayHistory()
{
return $this->belongsToMany(Driver::class, 'driver_route_history');
}
public function scopeWithDrivers($query, $date)
{
$carbon_date = Carbon::parse($date);
return $query
->when(
$carbon_date->isBefore(Carbon::today()->startOfWeek()),
function($query) use($carbon_date){
$query->with([
'driversOnDayHistory' => function($query) use($carbon_date){
$query->wherePivot('weekday', strtolower($carbon_date->shortDayName));
}
]);
},
function($query) use($carbon_date){
$query->with([
'driversOnDay' => function($query) use($carbon_date){
$query->wherePivot('date', $carbon_date);
}
]);
}
);
}
}
然后您可以在任何地方使用Route模型上的本地范圍
$records = Route::query()->withDrivers($date)->get();
因此,如果日期在過去$records
將有driversOnDayHistory
急切加載,否則它將有driversOnDay
急切加載。
有沒有辦法重命名屬性,所以它在兩種情況下都具有相同的名稱? 現在,加載的集合根據加載的關系命名不同。
您可以操作生成的集合。 假設您總是希望將預先加載的關系作為driversOnDay提供,那么您可以嘗試
$records = Route::query()
->withDrivers($date)
->get()
->map(function($route) {
if($route->relationLoaded('driversOnDayHistory')) {
$drivers = $route->driversOnDayHistory;
$route->unsetRelation('driversOnDayHistory');
$route->setRelation('driversOnDay', $drivers);
}
return $route;
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.