【问题标题】:how to order a JSON response based on database relationship using eloquent如何使用 eloquent 根据数据库关系订购 JSON 响应
【发布时间】:2023-03-20 06:17:01
【问题描述】:

我对 Laravel 还是很陌生,我正在尝试弄清楚如何正确使用 Eloquent,到目前为止效果很好,但我被困在我想做的事情中:

如果你计算迁移,我在数据库中有 3 个表 4:食物、食物组和部分,食物组和部分具有相同的结构,即 id 作为主键和名称列

食物有

 |  id(primary)  |  name  | food_group_id (foreign key) | portion_id (foreign key |

一切都很好,因为我的路线中有一个格式很好的 JSON

Route::get('/read', function() {

$categories = App\FoodGroup::with('Foods')->get();

 return Response::json(array('data' => $categories));
});

data: [
    {
       id: 1,
       name: "Frutas",
       foods: [
               {
                   id: 18,
                   name: "Acelga",
                   cant_portion: 2
               },
               {
                   id: 19,
                   name: "Espinaca",
                   cant_portion: 2
               },
              ]
    }
 ]

如果我用 App\Portion 更改 App\FoodGroup,它会给我相同的数组,但现在作为外键部分排序

我需要先用 FoodGRoup 订购,然后在 FFo_group 的每个项目中订购,现在按第二个外键(即部分)订购,这样我就可以拥有这样的东西

data: [
    {
       id: 1,
       name: "Frutas",
       portions:[
           id: 18,
           name: "Gr",  
           foods: [
               {
                   id: 18,
                   name: "Acelga",
                   cant_portion: 2
               },
               {
                   id: 19,
                   name: "Espinaca",
                   cant_portion: 2
               },
            ]
       ]           
    }
 ]

【问题讨论】:

  • $categories = App\FoodGroup::with('Foods','Portions')->get();这个呢??
  • @Drudgethat 不起作用,因为部分不在 FoodGroup 的模型中,我可以做 App\FoodGroup::with('Foods.portion')->get();它在每个项目上为我提供了表格部分的值,但我只想要一个值部分的数组,并在该数组中对它们进行排序,我不知道我是否足够清楚
  • 你能出示一下 food_group 和 part 的表格吗

标签: php mysql laravel


【解决方案1】:

您预期的 JSON 将 foods 显示为 portions 的子级。为此,您需要设置此关系。

在您的Portion 模型上,您需要设置以下关系:

public function foods() {
    return $this->hasMany(Food::class);
}

通过此关系设置,您现在可以像这样获取数据:

$categories = App\FoodGroup::with('portions.foods')->get();

这将加载您的食物组,然后将部分加载到食物组中,然后将食物加载到部分中。

编辑

我可能稍微误读了您的问题。我假设您在\App\FoodGroup 上定义了portions 关系。如果没有,您可以像这样添加:

食物组:

public function portions() {
    // the second parameter is the name of the pivot table.
    // in this case, your foods table connects your portions and food groups.
    return $this->belongsToMany(Portion::class, 'foods')->distinct();
}

编辑 2

这个解决方案有点笨拙,因为它将foods 表视为数据透视表,尽管它不是专门为此设计的。因此,foods 表中有多个条目包含相同的密钥对值,这就是您获得重复相关模型的原因。

如果您将distinct() 扔到关系上,这应该可以解决问题,因为它将消除从内部连接创建的重复项。上面的代码已经修改了。

【讨论】:

  • 我想你知道我想要什么,一件事我尝试了你输入的代码,但它没有用我想我应该把类 thibg 换成别的东西?因为我在 Builder::portions() 中得到了 BadMethodCallException
  • @AllanAlvarezOrtiz 我已根据您的评论更新了我的答案。
  • 是的!这就是我想要的,但是,它重复每个项目我的意思是它正确地做到了i.imgur.com/Xjuvl4L.png 我的意思是如果部分对象中有 10 个项目,它会创建 10 个部分列表,我只需要 1 个
  • 实际上它会在这里随机看到 Json:codebeautify.org/jsonviewer/cb9a9d16
  • 谢谢@patricus,它工作得很好,标记为正确答案!
【解决方案2】:

根据您发送的图片(即您的餐桌),food_group 与部分没有直接关系,因此您不能将 food_group 与这样的部分链接

  App\FoodGroup::with('portion.foods')

它应该是(这就是你在 Builder::portions() 中得到 BadMethodCallException 的原因)

 App\FoodGroup::with('foods.portion')

因为foodgroup 有很多食物,而食物有很多份。所以你可以尝试这样的事情

App\FoodGroup::with(['foods.portion'=>function($q){
   $q->orderBy('id')
}])->get(); 

【讨论】:

  • 感谢您的帮助,不是精确而是关闭,我现在想要的是查看我的 json:i.imgur.com/JzYcWoz.png 你会看到在每个项目中我有一个部分数组,并且它每次重复新项目出现,我想要的不是重复,只需放入一次并在里面获取与该部分匹配的所有项目
  • 加载“foods.portion”并没有给出所请求的结构。这将使食物对象内的部分对象。 OP 已请求部分对象内的食物对象。
  • 此外,由于预加载的工作方式,您不能在预加载约束内指定限制(通过take(1) 完成)。这不会将负载限制为每个食物组一种食物,而是将负载限制为一个食物时段。如果有 1000 个食物组,这仍然只会加载 1 个食物记录,而不是预期的 1000 个。
  • 是的,我只能使用我得到的数组 App\FoodGroup::with('foods.portion') 和你发送给你的数组,所以我无法实现我想要的吗?导致解决方案 keeos 说我这是一个意想不到的 '}' 我觉得很奇怪
  • @patricus 我在发布之前测试了代码我不只是发布。您可以尝试,laravel 会为您限制它。 take(1) 在急切加载中确实有效
猜你喜欢
  • 2014-08-27
  • 2019-07-18
  • 2021-09-28
  • 1970-01-01
  • 2021-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-21
相关资源
最近更新 更多