Красноречивый запрос, дающий данные из неправильной строки - PullRequest
0 голосов
/ 24 июня 2018

Некоторое время назад я начал свой первый проект с 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  |                  |
|---------------------|------------------|------------------|

Если хранилища принадлежат пользователям, хранилища содержат элементы, а storage_contents - это сводная таблица между этими двумя.

Если кому-то интересно, почему я не просто поместил expiry_date и amount в таблицу Items, но в их собственную сводную таблицу, то это потому, что я намеревался сделать так, чтобы пользователи могли использовать элементы друг друга в свои собственные хранилища. Так, например, если один пользователь создал элемент Apple. Когда другой пользователь начинает вводить это, он получает раскрывающийся список с возможностью выбрать ранее созданный элемент Apple от другого пользователя. Но хотя имя, описание, изображение и ккал могут совпадать, сумма и срок действия могут отличаться от пользователя к пользователю. Поэтому я положил его в сводную таблицу.

Что было хорошо, пока я не попытался запустить этот красноречивый запрос:

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

Где storageContent() - красноречивое отношение из модели Предметов:

public function storageContent(){

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

}

Но по какой-то причине, когда я выполняю этот запрос, я получаю данные только из первой записи таблицы (независимо от того, какой идентификатор я ввел в запрос), но данные сводной таблицы равны из правый сводный стол. Но я не могу на всю жизнь понять, , почему это происходит.

Чтобы уточнить, что я получаю и что ожидаю получить с помощью этого запроса:

Когда я ставлю запрос в ремесленник, повозиться:

Скажем, у меня в таблице предметов 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.

Когда я ввожу $item = Items::find(1)->storageContent()->get(); в Artisan tinker, я получаю:

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,
     },
   },
 ],
}

Может, у кого-нибудь из вас есть представление о том, что я сделал не так?

Ответы [ 2 ]

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

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

Итак, у меня были такие отношения раньше в моей Items модели:

публичной функцииstorageContent () {

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

Но я думаю, что неправильно понял, какие строки я должен был туда ввести, потому что storage_id, так как связанный ключ не имеет смысла никакого смысла (вретроспектива).Причина, если я изменю его просто на id (он же строка id в таблице Item), например:

открытая функция storageContent () {

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

itработает так, как я ожидаю.

Я все же хотел бы поблагодарить всех, кто пытался помочь мне и пытался найти решение для моей проблемы.

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

В вашей 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

UPDATE

Я только что попробовал, это не то, что я хотел. Может быть, это поможет, если я объясню, где мне нужно использовать этот запрос. Когда пользователь находится в хранилище, он / она может видеть, какие предметы находятся в этом хранилище. Когда пользователь нажимает на элемент, модал должен появиться и показать информацию об этом элементе (имя, описание, ккал, количество, срок годности), чтобы заполнить этот модал.

Как вы сказали в комментариях, когда пользователь обращается к элементу в хранилище, вы хотите показать модал с опорными столбцами. Таким образом, когда пользователь впервые получает доступ к хранилищу, вы, вероятно, должны получить Storage со всеми его элементами, чтобы каждый элемент имел столбцы сводных данных. Может быть, вы хотите обратное тому, что я вам дал. Вы можете увидеть изменения выше.

Однако, если вам нужен только один элемент из хранилища, то, вероятно, у вас уже есть storage или его id. Затем вы можете попробовать это:

$storage = Storage::findOrFail($storageId)

Тогда вы можете получить один предмет, используя это:

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

Это может помочь вам.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...