Изменение выборки из таблицы, модель которой в зависимости “hasMany” Laravel 8

У меня есть модель Product и таблица Products. Так же есть связанная таблица и модель ProductImage через hasMany.

Модель Product
    public function productimage()
  {
      return $this->hasMany(ProductImage::class);
  }

И теперь когда я делаю выборку например $prod=Product::get(); А затем во вью через @foreach перебираю их, а когда дело доходит до картинок то использую связь: @foreach($prod->productimage as $img), то выводятся все картинки. Но так же у менять есть карточка товара, для который не нужны все картинки, а только первая, для этого у меня в таблице ProductImages предусмотрено поле position, так вот, как мне её реализовать, пробовал через муттаторы, но что то не получилось:

Модель ProductImage
public function getCardImgAttribute() {
    return ProductImages::where('position', 1)->get();
  }

А во вью через {{$img->card_img}} выводится массив вместо одной ссылки на изображение:

src="/img/products/[{"path":"img_1.jpg"},{"path":"img_6.jpg"},{"path":"img_10.jpg"},{"path":"img_16.jpg"}]".

По идее должна выводиться ссылка для каждого элемента, а получилось что в каждом элементе 4 ссылки.

Я понимаю, что нигде не указал поле "path", которое отвечает за ссылку, я не могу понять, где я его должен указать. Что то типа {{$img->card_img->path}} не работает.

Помогите исправить, пожалуйста.


Ответы (1 шт):

Автор решения: Вадим Александру
public function getCardImgAttribute() {
    return ProductImages::where('position', 1)->get();
  }

У вас в этом коде допущена логическая ошибка, этот метод будет возвращать коллекцию из всех ProductImages у которых position = 1 а не связаных с данным объектом.

В таком случае, вы можете сделать еще одно отношение hasOne в объекте Product таким образом

   public function cardImage()
  {
      return $this->hasOne(ProductImage::class)->where('position', 1);
  }

Далее юзать его таким образом:

$product = Product::query()->first();

dd($product->cardImage->path);

Так же второй вариант: Суть в том, чтобы из коллекции всех картинок выбрать ту, у которой position = 1

public function cardImage()
{
  return $this->productimage->find(function(ProductImages $image) {
    return 1 === $image->position;
});
}

Во втором случае, не будет дополнительного запроса к базе данных. Если одновременно вам нужно использовать методы cardImage и productImage тогда лучше использовать второй вариант ибо в таком случае будет лишь один запрос к базе данных. В инном случае лучше первый, запрос к базе все равно один, но каждый ваш экземпляр product будет дополнительно держать в памяти еще и коллекцию из ProductImages, при том что нужно лишь один элемент. Но это только когда вы дойдете до оптимизации производительности.

→ Ссылка