【问题标题】:Eloquent query giving data from the wrong row雄辩的查询从错误的行提供数据
【发布时间】:2018-12-03 06:00:26
【问题描述】:

不久前,我用 Larvel 开始了我的第一个项目,并在我的 Elequent 查询中遇到了这个奇怪的问题。

所以我有 3 张桌子:

|---------------------|------------------|------------------|
|       storage       |       items      | storage_contents |
|---------------------|------------------|------------------|
|         id          |        id        |        id        |
|---------------------|------------------|------------------|
|       user_id       |       name       |    storage_id    |
|---------------------|------------------|------------------|
|        name         |    description   |     item_id      |
|---------------------|------------------|------------------|
|     description     |       kcal       |      amount      |
|---------------------|------------------|------------------|
|                     |      img_url     |    expiry_date   |
|---------------------|------------------|------------------|
|                     |  always_on_list  |                  |
|---------------------|------------------|------------------|

storages 属于用户,storages 包含项目,storage_contents 是这两者之间的数据透视表。

如果有人想知道为什么我不只是将 expiry_dateamount 放在 Items 表中,而是放在他们自己的数据透视表中,那是因为我打算这样做,以便用户可以使用彼此的项目他们自己的仓库。例如,如果一位用户创建了 Apple 项目。当另一个用户开始输入时,他们会看到一个下拉菜单,其中包含从其他用户那里选择先前创建的 Apple 项目的选项。但是,虽然名称、描述、图像和千卡可能相同,但数量和到期日期可能因用户而异。因此我把它放在了一个数据透视表中。

在我尝试运行这个 Eloquent 查询之前一切正常:

$item = Items::find($id)->storageContent()->get();

storageContent() 是 Items 模型中的 Eloquent 关系:

public function storageContent(){

    return $this
        ->belongsToMany(Items::class,'storage_contents','item_id','storage_id')
        ->withPivot('amount','expiry_date');

}

但是由于某种原因,当我执行这个查询时,我只从第一个表条目中获取数据(不管我在查询中输入了什么 ID),但是数据透视表的数据来自正确的数据透视表。但我终其一生都无法弄清楚为什么会发生这种情况。

澄清我得到什么以及这个查询期望得到什么:

当我将查询放入 Artisan tinker 时:

假设我的 Items 表中有 2 个项目:

|-------------------|-------------------|
|       items       |       items       |
|-------------------|-------------------|
|       id: 1       |       id: 2       |
|-------------------|-------------------|
|     name: foo     |     name: bar     |
|-------------------|-------------------|
| description: null | description: null |
|-------------------|-------------------|
|    kcal: null     |    kcal: null     |
|-------------------|-------------------|
|   img_url: null   |   img_url: null   |
|-------------------|-------------------|
| always_on_list: 0 | always_on_list: 0 |
|-------------------|-------------------|

其中 foo 的数量为 123,bar 的数量为 321。

当我在 Artisan tinker 中输入 $item = Items::find(1)->storageContent()->get(); 时,我得到:

Illuminate\Database\Eloquent\Collection {#109
 all: [
   App\Items {#2337
     id: 1,
     name: "test1",
     description: "foo",
     kcal: null,
     img_url: null,
     always_on_list: 0,
     created_at: "2018-06-24 15:12:03",
     updated_at: "2018-06-24 15:12:03",
     pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2332
       item_id: 1,
       storage_id: 1,
       amount: 123,
       expiry_date: null,
     },
   },
 ],
}

这符合我期望得到的结果,但是当我这样做 $item = Items::find(2)->storageContent()->get(); 时,我得到:

Illuminate\Database\Eloquent\Collection {#109
 all: [
   App\Items {#2337
     id: 1,
     name: "test1",
     description: "foo",
     kcal: null,
     img_url: null,
     always_on_list: 0,
     created_at: "2018-06-24 15:12:03",
     updated_at: "2018-06-24 15:12:03",
     pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2332
       item_id: 2,
       storage_id: 1,
       amount: 321,
       expiry_date: null,
     },
   },
 ],
}

这不是我期望得到的,我期望得到:

Illuminate\Database\Eloquent\Collection {#109
 all: [
   App\Items {#2337
     id: 2,
     name: "test2",
     description: "bar",
     kcal: null,
     img_url: null,
     always_on_list: 0,
     created_at: "2018-06-24 15:12:03",
     updated_at: "2018-06-24 15:12:03",
     pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2332
       item_id: 2,
       storage_id: 1,
       amount: 321,
       expiry_date: null,
     },
   },
 ],
}

也许你们中的任何人都知道我做错了什么?

【问题讨论】:

  • 什么是右数据透视表?如果您正在谈论我雄辩的术语,请告诉我表格名称或型号名称......不要指明表格的方向。请明确说明从当前查询中得到什么以及您期望什么?
  • @Ruman 对不起,我添加了一个示例,说明我期望得到什么以及我实际得到什么。

标签: laravel eloquent


【解决方案1】:

抱歉,暂时没有回复。我只是再次查看了我的问题/代码,并找到了另一个似乎可以解决我的问题的解决方案。

所以,我之前在我的Items 模型中有这种关系:

公共函数 storageContent(){

return $this
    ->belongsToMany(Items::class,'storage_contents','item_id','storage_id')
    ->withPivot('amount','expiry_date');
}

但我想我误解了我应该在那里输入的行,因为storage_id 因为相关键没有任何意义(回想起来)。因为如果我将其更改为 id(又名 Item 表中的 id 行),如下所示:

公共函数 storageContent(){

return $this
    ->belongsToMany(Items::class,'storage_contents','item_id','id')
    ->withPivot('amount','expiry_date');
}

它像我期望的那样工作。

我仍然要感谢大家尝试帮助我并尝试为我的问题找到解决方案。

【讨论】:

    【解决方案2】:

    在您的Storage 模型中:

    public function items() 
    { 
        return $this->belongsToMany(
            Items::class,
            'storage_contents',
            'item_id',
            'storage_id'
        )->withPivot('amount','expiry_date'); 
    }
    

    并查询:

    $storage = Storage::where('id', $id)->with('items')->firstOrFail();
    

    您可以通过以下方式访问视图中的数据透视列:

    @foreach($storage->items as $item)
        <ul>
            <li>Amount - {{$item->pivot->amount}} </li>
            <li>Expiry - {{$item->pivot->expiry_date}} </li>
        </ul>
    @enforeach
    

    更新

    我刚刚试了一下,这不是我想要的。如果我解释我需要在哪里使用此查询,也许会有所帮助。当用户在存储位置时,他/她可以看到该存储位置中有哪些物品。当用户点击一个商品时,需要弹出一个modal,并显示该商品的信息(名称、描述、kcal、金额、有效期)来填写该modal。

    正如您在 cmets 中所说,当用户访问存储中的项目时,您希望显示带有枢轴列的模式。因此,当用户第一次访问存储时,您可能应该得到 Storage 及其所有项目,这样每个项目都有枢轴列。也许你想要我给你的相反。你可以看到上面的变化。

    但是,如果您只想要存储中的单个项目,那么您可能已经拥有storage 或其id。然后,你可以试试这个:

    $storage = Storage::findOrFail($storageId)
    

    然后你可以使用这个来获得单个项目:

    $items = $storage->items()->where('id', $itemId)->firstOrFail();
    

    这可能会对你有所帮助。

    【讨论】:

    • 我不想用这个查询获取存储的信息,我想从我给它的项目ID相关的数据透视表中获取项目信息和信息。
    • 好的。当您发布问题时,请始终提供必要的详细信息。我会更新我的答案。
    • 对不起,这是我在 StackOverflow 上的第一个问题。以后我会努力提供更好的信息。
    • 没关系!我已经更新了我的答案。让我知道它是否有效。
    • 我刚试过,不是我想要的。如果我解释我需要在哪里使用此查询,也许会有所帮助。当用户在存储位置时,他/她可以看到该存储位置中有哪些物品。当用户点击某个商品时,需要弹出一个modal,并显示该商品的信息(名称、描述、kcal、金额、有效期)来填写该modal。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-07-07
    • 2018-01-26
    • 2014-04-12
    • 2021-07-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多