【问题标题】:laravel sum of property in parent *and* children models?laravel 父 * 和 * 子模型中的属性总和?
【发布时间】:2021-05-04 01:39:45
【问题描述】:

我有出现在时间轴中的地点。这些地点可以分组:父地点可以有子地点(只有一层深)。

想要延迟加载地点,包括该地点及其子项的访问次数,并按总次数排序。
有太多的地方不能把它们全部放在前面,然后再进行求和和排序。

我试图得到的结果的简化示例:

- place B - visits 5, visits children 6, total visits 11
  - place B.1 - visits 2
  - place B.2 - visits 4
- place A - visits 5, visits children 0, total visits 5
- place C - visits 1, visits children 2, total visits 3
  - place C.1 - visits 2

通过下面的代码,除了“总访问量”之外,我得到了所有这些信息。

我在 Place 模型中使用简单的关系:

public function children(){
  return $this->hasMany(Place::class, 'parent_id');
}

public function visits(){
  return $this->hasMany(Timeline::class);
}

public function visitsChildren(){
    return $this->hasManyThrough(
        Timeline::class, // the end result
        Place::class, // going through this one
        'parent_id', // foreign key on Place (child)
        'place_id', // foreign key on Timeline
        'id', // local key on Place (parent)
        'id' // local key on Place (child)
    );
}

我可以获得那个地方的访问次数以及孩子们和他们的访问次数。

\App\Models\Place::where(...)
  ->withCount('visits', 'visitsChildren')
  ->with('children', fn($q) => $q->withCount('visits'))
  ->orderByDesc('visits_count')
  ->get()

但是如何将它们相加并按总数排序(无需预先加载)?
IE。我可以“合并”visitsvisitsChildren 吗?

试过了,但那不起作用,因为列visits_countvisits_children_count(可以理解)在该级别不可用:

...
->select(DB::raw('visits_count + visits_children_count as visits_including_children_count'))
->get()

更新:添加了visitsChildrenDB::raw 尝试的关系。

【问题讨论】:

    标签: laravel eloquent


    【解决方案1】:

    你可以使用laravel collectionmap()sum()方法解决这个问题

    $result = \App\Models\Place::where(...)
        ->withCount('visits')
        ->with('children', fn($q) => $q->withCount('visits'))
        ->orderByDesc('visits_count')
        ->get();
    
    $count = $result->map(function ($item) {
        $children_count = $item->children->sum(function ($child) {
            return $child->visits_count ?? 0;
        });
        return $children_count + $item->visits_count;
    });
    dd($count);
    

    【讨论】:

    • 这会在获得地点之后完成工作。我需要信息得到它们之前。
    猜你喜欢
    • 2021-06-24
    • 1970-01-01
    • 2016-11-17
    • 2017-06-24
    • 2016-05-10
    • 2016-03-30
    • 2016-08-15
    • 1970-01-01
    • 2018-06-04
    相关资源
    最近更新 更多