Laravel中的急切负载与参数的关系

发布于 2025-02-06 08:35:35 字数 1352 浏览 5 评论 0原文

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

我有两个具有相同列的枢轴表,称为driver_routedriver_route_history。他们都将driver_idroute_id列相关联。唯一的区别是driver_route_history具有date列,该列具有绝对时间的日期(例如06/08/2022),而driver_route具有工作日列,该列是指本周。

用户可以修改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::with(['driversOnDay' => function($query) { ... });

如何包括driversonday driversonday < /code> date参数到此急切的加载调用中?

In my Laravel app, I want to have a relation conditionally load data from one of two tables, depending on a specified parameter.

I have two pivot tables with identical columns, called driver_route and driver_route_history. They both relate driver_id and route_id columns. The only difference is driver_route_history has a date column which holds an absolute date in time (e.g. 06/08/2022), while driver_route has a weekday column which refers to the current week.

The records in driver_route can be modified by the user. At the end of each week, they are cloned to driver_route_history, so that changes from week to week are preserved looking back.

I want to be able to pull data for a single day. If the specified day falls within the current week or references a future date, data should be loaded from driver_route. If the date falls prior to the start of the current week, data should be pulled from driver_route_history.

I have a function that can do this, when called ordinarily as a function from somewhere within the app:

    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));
        }
    }

I would like to load this relation on every Route record using Laravel's eager loading, like such:

Route::with(['driversOnDay' => function($query) { ... });

How can I include the driversOnDay date parameter into this eager load call?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

つ低調成傷 2025-02-13 08:35:35

据我了解,模型路线驱动程序模型通过多次关系,您需要通过driver_route 枢轴表如果$ date在当前周或以后,并且通过driver_route_history pivot表,如果$ date是较早的比本周的开始。

一种方法是在模型上定义两个单独的关系,然后使用一个范围:

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();

然后 $记录将具有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;
    });

From what I understand, model Route is associated with Driver model via many-to-many relationship and you need to join the relation via driver_route pivot table if the $date is in current week or in future and via driver_route_history pivot table if $date is older than start of current week.

One way of doing it would be to have two separate relationships defined on the model and then use a scope:

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);
                        }
                    ]);
                }
            );
    }
}

Then you can use the local scope on Route model anywhere

$records = Route::query()->withDrivers($date)->get();

So if the date is in past $records will have driversOnDayHistory eager loaded else it will have driversOnDay eager loaded.

Update

Is there a way to rename the attribute, so it has the same name in both cases? Right now, the loaded collections are named differently depending on which relation was loaded.

You can manipulate the resulting collection. Say you always want to have the eager loaded relations available as driversOnDay, then you can try

$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;
    });
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文