2017-11-25 230 views
0

我有一个基于Laravel 5.2的配方构建应用程序。按多个字段分组,然后生成总和

用户可以添加配料到他们的食谱中,偶尔你可以添加相同的配料两次,这取决于你使用的配料是什么。

我正在构建允许用户为其配方生成购物清单的功能,这应该为它们生成PDF购物清单。

到目前为止,我列出了正在生成的成分,但我无法完全理解如何进行分组和汇总数量。

一个典型的列表可能是这样的:

[ 
    { 
     "id":97724, 
     "name":"Citra Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
    }, 
    { 
     "id":97725, 
     "name":"Simcoe Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
    }, 
    { 
     "id":97726, 
     "name":"Citra Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
    }, 
    { 
     "id":97727, 
     "name":"Simcoe Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
    }, 
    { 
     "id":97729, 
     "name":"Mosaic Pellets", 
     "amount":79.9999, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
    }, 
    { 
     "id":97730, 
     "name":"Simcoe Pellets", 
     "amount":60, 
     "hop_type_id":"Combined", 
     "recipe_id":23453 
    } 
] 

目前,我只是有一个foreach循环会超过这些在我看来,吐出的结果;它出来是这样的:

+--------+----------------+------------+ 
| Amount |  Name  | Usage Type | 
+--------+----------------+------------+ 
| 6.5 | Citra Pellets | Pellet  | 
| 6.5 | Simcoe Pellets | Pellet  | 
| 6.5 | Citra Pellets | Pellet  | 
| 6.5 | Simcoe Pellets | Pellet  | 
| 79.99 | Mosaic Pellets | Pellet  | 
|  60 | Simcoe Pellets | Combined | 
+--------+----------------+------------+ 

我所想要做的就是按自己的名称和使用类型的成分,然后得到的金额总和。所以输出是这样的:

+--------+----------------+------------+ 
| Amount |  Name  | Usage Type | 
+--------+----------------+------------+ 
|  13 | Citra Pellets | Pellet  | 
|  13 | Simcoe Pellets | Pellet  | 
| 79.99 | Mosaic Pellets | Pellet  | 
|  60 | Simcoe Pellets | Combined | 
+--------+----------------+------------+ 

我尝试到目前为止已包括App\Models\Recipe::find(23453)->hops->groupBy('name') - 这让我有点像下面:

{ 
    "Citra Pellets":[ 
     { 
     "id":97724, 
     "name":"Citra Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
     }, 
     { 
     "id":97726, 
     "name":"Citra Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
     }, 
     { 
     "id":97728, 
     "name":"Citra Pellets", 
     "amount":94.9999, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
     } 
    ], 
    "Simcoe Pellets":[ 
     { 
     "id":97725, 
     "name":"Simcoe Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
     }, 
     { 
     "id":97727, 
     "name":"Simcoe Pellets", 
     "amount":6.5, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
     }, 
     { 
     "id":97730, 
     "name":"Simcoe Pellets", 
     "amount":60, 
     "hop_type_id":"Combined, 
     "recipe_id":23453 
     } 
    ], 
    "Mosaic Pellets":[ 
     { 
     "id":97729, 
     "name":"Mosaic Pellets", 
     "amount":79.9999, 
     "hop_type_id":"Pellet", 
     "recipe_id":23453 
     } 
    ] 
} 

然后,这让我可以遍历每个然后->sum('amount')得到总和值。但是它没有考虑hop_type_id这很重要。

我也尝试过链接->groupBy('hop_type_id'),以及使用->each(function ($item, $key))的变体,但还没有设法解决这个问题。

它看起来像集合上的初始groupBy()会生成一个键值对象,其中有一个值的数组。

我理想之后是在hop_type_id中的每个跳跃名称下的另一个级别,然后我可以使用它生成每跳namehop_type_id的总和。

我该如何做到这一点?

回答

0

我认为你正在寻找这个 -

\App\Ingredient::where('recipe_id','=',23453)->selectRaw('sum(amount) as amount, name, hop_type_id')->groupBy('name')->groupby('hop_type_id')->get(); 

希望它能帮助:)

+0

我给这个一展身手,但渴望与现有的查询来实现这一目标。 – James

+0

@詹姆斯有时需要部分分解是必要的,如果它帮助,然后让我知道,我会尝试与您现有的查询。 – Sohel0415

0

你可以重写整个招待作为原料的数组。这样一个招待对象的类型将是

 Ingredient[] 

每种成分将具有以下私有字段与相应的公共干将

  $id, (string) $name, (int) $amount, $hop_type_id, $recipe_id 

然后,您可以生成一个购物清单像如下

$shoppingList = []; 
foreach($recept as $ingredient) { 
    $shoppingList[$ingredient->getName()] += $ingredient->getAmount(); 
} 
+0

这是一个现有应用程序的新功能,不可悲的重写。 – James

+0

如果在foreach循环的结果中,只是检查某个成分是否已经添加到列表中,该怎么办?如果是,则只需添加新数量,而在另一种情况下,则向列表中添加新元素。如果你发布你的foreach循环,我可以更具体一些。 – Annibale

0

所以我使用现有的集合来解决它,而不必使用原始查询或修改数据库模式。

您可以使用groupBy()然后transform()来实现这一目标:

$recipe = App\Models\Recipe::find(23453); 

$hops = $recipe->hops->groupBy('name') 
     ->transform(function ($hop, $key) { 
      return $hop->groupBy('hop_usage_type'); 
     }); 
相关问题