在Laravel中与参数的动态加载关系



在我的Laravel应用程序中,我想有一个关系,根据指定的参数有条件地从两个表中的一个加载数据。

我有两个具有相同列的数据透视表,称为driver_routedriver_route_history。它们都与driver_idroute_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) { ... });

如何将driversOnDaydate参数包含到这个急切加载调用中?

据我所知,modelRouteDriver关联通过建立多对多模型如果$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;
});

相关内容

  • 没有找到相关文章

最新更新