Laravel сокращает отношения запросов - PullRequest
0 голосов
/ 30 июня 2018

У меня две модели. Expense и Method. Я хочу получить sum всех expenses за каждый method type. У меня есть четыре типа:

- bank
- credit-card
- wallet
- savings

Каждый расход принадлежит методу, и каждый метод имеет много расходов. Так что это отношение «один ко многим». Таким образом, method_id сохраняется для каждого Расхода.

Следующий запрос работает для получения суммы всех расходов, для которых есть метод с типом bank, например:

$type = 'bank';

$expenses = auth()->user()->expenses()->with('method')->whereHas('method', function ($query) use ($type) {
        $query->where('type', $type);
    })->sum('amount');

Но дело в том, что если я хочу получить общую сумму всех расходов для каждого типа метода, мне придется выполнять слишком много запросов. Я бы предпочел просто захватить все расходы и затем отфильтровать их, чтобы получить сумму всех расходов для каждого типа метода.

Следующее, например, не работает:

$expenses = auth()->user()->expenses()->with('method')->get();

    $bank_balance = $expenses->filter(function ($expense)
    {
        $expense->whereHas('method', function ($query) {
            $query->where('type', 'bank');
        })->get(); // with or without ->get()
    });

Есть идеи, как получить то, что я хочу, не используя слишком много запросов?

Edit:

Я не принял выбранный ответ, потому что он не дал мне то, что мне было нужно в конце. Мне нужно быть в состоянии сделать что-то подобное, на мой взгляд:

{{ $bank_balance }}

Что означает, что с ответом xyz я не смогу этого сделать, поскольку не могу их различить. Я получаю результаты только на основе method_id, но мне нужно иметь возможность различать их по имени метода.

Ответ DigitalDrifter - тот, который почти добивается цели, но он дает мне это:

Collection {#800 ▼
  #items: array:3 [▼
    "bank" => Collection {#797 ▼
      #items: array:30 [▼
        0 => array:2 [▼
          "type" => "bank"
          "amount" => 1536
        ]
        1 => array:2 [▶]
        2 => array:2 [▶]
        3 => array:2 [▶]
        4 => array:2 [▶]
        5 => array:2 [▶]
      ]
    }
    "credit-card" => Collection {#798 ▶}
    "wallet" => Collection {#799 ▶}
  ]
}

И мне в основном нужно что-то простое, как это:

"bank" => "общая сумма здесь для всех расходов, которые имеют метод" bank "" "credit-card" => "общая сумма здесь для всех расходов, которые имеют метод" credit-card ""

И так далее ..

Я думаю, что этот бит ->groupBy('type')->each->sum('amount') добивается цели, но не полностью. Он группирует по типу, но не дает суммы для каждого типа, как вы можете видеть в приведенном выше примере коллекции.

Ответы [ 2 ]

0 голосов
/ 30 июня 2018

Вы можете сделать это, используя доступные методы сбора:

$expenses = auth()->user()->expenses()->with('method')->get();

$groupedSums = $expenses->map(function ($expense) {
    return [
        'type' => $expense['method']['type'],
        'amount' => $expense['method']['amount']
    ];
})->groupBy('type')->each->sum('amount');
0 голосов
/ 30 июня 2018

Вы можете сгруппировать по идентификатору метода и затем суммировать результат в операторе выбора.

Не проверено следующее.

$expenses = auth()->user()
                  ->expenses()
                  ->select(DB::raw('SUM(amount) as total'), 'other_select_fields', ...)
                  ->with('method')
                  ->groupBy('method_id')
                  ->get();
...