Laravel 8 красноречивые вопросы с отношениями

#php #laravel

Вопрос:

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

Модели

 class Product extends Model {
    public function getAllData()
    {
        $data = DB::table('product')
            ->select('product.*', 'product_images.img')
            ->join('product_images', 'product_images.product_id', '=', 'product.id')
            ->paginate(9);
        return $data;  
    }
}
 
 class ProductImage extends Model
{
    public function product()
    {
        return $this->belongsTo(product::class);
    }
}
 

Контроллер

 public function index()
{
    $img = ProductImage::find(1);
    $data = [
        'card' => $img->product->getAllData(),
    ];
    return view('view', $data);
}
 

Вид

 @foreach ($card as $item)
<div class="card shadow m-3" style="width: 18rem; heigth:24rem">
  <div class="inner">
    <img class="card-img-top" src="{{$item->img}}" alt="Card image cap">
  </div>
  <div class="card-body text-center">
    <h5 class="card-title">{{$item->name}}</h5>
    <p class="card-text">{{$item->description}}</p>
    <a href="">Check them out...</a>
  </div>
</div>
@endforeach
 

Поэтому я хочу получить все Product экземпляры с ProductImage экземплярами в одном массиве $card . Как правильно это сделать?

Заранее спасибо.

Ответ №1:

Что я понимаю из вашего требования, так это то, что вы хотите отобразить все продукты, у которых есть по крайней мере 1 изображение на продукте.

 public function index()
{
    $products = Product::has('image')
       ->with('image')
       ->get();
    $data = [
        'card' => $products,
    ];
    return view('view', $data);
}
 

Это вернет все продукты, у которых есть 1 изображение, и изображение может быть использовано через image отношение

 @foreach ($card as $item)
<div class="card shadow m-3" style="width: 18rem; heigth:24rem">
  <div class="inner">
    <img class="card-img-top" src="{{$item->image->img}}" alt="Card image cap">
  </div>
  <div class="card-body text-center">
    <h5 class="card-title">{{$item->name}}</h5>
    <p class="card-text">{{$item->description}}</p>
    <a href="">Check them out...</a>
  </div>
</div>
@endforeach
 

Модель продукта

 class Product extends Model 
{
    public function image()
    {
        return $this->hasOne(ProductImage:class);
    }
   
    public function images()
    {
        return $this->hasMany(ProductImage:class);
    }
}
 

Я использовал только Laravel Eloquent, поэтому то, как я показал визуализацию рассматриваемых продуктов, может быть неправильным

Комментарии:

1. Я не понимаю, почему понижают голос, лучше тоже прокомментировать

2. Я не собираюсь голосовать против. Ваш код работает, но он использует отношение «один к одному». Давайте предположим, что у каждого продукта есть три изображения, и я хочу отобразить одно из них.

3. Разгадал ее! Я перешел в hasMany() и добавил нулевой индекс, чтобы получить первое изображение в коллекции $item->image->img . Так что это будет $item->image[0]->img вам спасибо!

4. @AriefG Я использовал соотношение «один к одному», потому что вам требовалось отображать только одно изображение, и даже после изменения этого соотношения на «один ко многим» вы делаете то же самое, hasOne что и сейчас. Я просто говорю это с точки зрения оптимизации