在我的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的eager loading将这个关系加载到每条Route记录上,就像这样:
Route::with(['driversOnDay' => function($query) { ... });
如何将driversOnDay
date
参数包含到这个急切加载调用中?
据我所知,modelRoute与Driver关联通过建立多对多模型如果$date
在当前周或未来,则需要通过driver_route
数据透视表加入关系,如果$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上使用local作用域模型在
$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;
});