Triumfator's avatar

How to display multiple images for a product in Laravel 5.8

I have 2 models. Item & ItemImage. Eloquent model relationships are defined in those models. Each item can have MANY different images, and each image can belong to only one item.

Item Model

<?php

namespace App;

use EloquentFilter\Filterable;
use Illuminate\Database\Eloquent\Model;

class Item extends Model 
{

  protected $table ='items';
  protected $primaryKey = 'id';

 public function itemphotos() 
  {
    return $this->hasMany('App\ItemImage'); 
  }

}

ItemImage model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class ItemImage extends Model
{
    protected $table = 'itemimages';
    protected $primaryKey='id';
    protected $fillable = ['item_id', 'name'];

    public function item() {
        return $this->belongsTo('App\Item');
    }

}

My routes are set like this

Route::resource('image-gallery','ItemImageController');
  Route::resource('/item', 'ItemController');

ItemImageController

<?php

namespace App\Http\Controllers\Admin;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Http\Requests;
use DB;
use Validator;
use Redirect;
use View;
use Image;
use File;



// import the storage facade
use Illuminate\Support\Facades\Storage;

//import ItemImage model.
use App\ItemImage;

// import Item model.
use App\Item;

class ItemImageController extends Controller
{
  
    public function store(Request $request)
    {
        $request->validate([
        'images' => 'required',
        'images.*' => 'image|max:2048|mimes:jpeg,png,jpg,gif,svg'
        ]);
        
        $input = $request->all();
   

        // Gets item id from upload images form
        $item_id = $request->input('item_id');
        
        // Names of folders
        $itemimagefolder = public_path().'/itemimages/' . $item_id;
        $itemimagethumbsfolder = public_path().'/itemimages/' . $item_id . '/thumbs';

        // Makes folders for storing images and thumbs for each item if it doesn't exist. 
        // Works with 493 permission instead of 0755 on windows.
        if( ! File::exists($itemimagefolder)) {
            File::makeDirectory($itemimagefolder, 0755, true);
        }
        if( ! File::exists($itemimagethumbsfolder)) {
            File::makeDirectory($itemimagethumbsfolder, 0755, true);
        }
        
        $inputData=$request->all();
        if($request->file('images')){
            
            $images=$request->file('images');
            
            // loop through each image to save and upload
            foreach ($images as $image){
                if($image->isValid()){
                    $extension=$image->getClientOriginalExtension();
                    $filename=rand(100,999999).time().'.'.$extension;
                    
                    $large_image_path=($itemimagefolder.'/'.$filename);
                    $small_image_path=($itemimagethumbsfolder.'/'.$filename);
                    
                    // Resize Images
                    Image::make($image)->save($large_image_path);
                    Image::make($image)->resize(225,169)->save($small_image_path);
                        
                    // Passes filename to $inputData variable for database write
                    $inputData['name']=$filename;
                    
                    // writes to database via eloquent model
                    ItemImage::create($inputData);
                }
            }
        }
        
        return back()->with('status','Images added successfully.');
        
    }  
    
    public function show($id)
    {
        
        $item=Item::findOrFail($id);
        $imageGalleries=ItemImage::where('item_id',$id)->get();
        //dd($imageGalleries);
        return view('admin.itemgallery',compact('item','imageGalleries'));
    }

}

Migration for itemimages table is shown below.

 public function up()
    {
        Schema::create('itemimages', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->unsignedBigInteger('item_id');
            $table->string('name', 256);
            $table->timestamps();
            $table->foreign('item_id')
            ->references('id')->on('items')
            ->onDelete('no action')
            ->onUpdate('no action');

        });
    }

Basically, my uploading works flawlessly and images are stored properly in a public folder. I can properly display images associated with a particular item through the ItemImageController's show function. For example "http://localhost/admin/image-gallery/45" will display images of items associated with item #45.

Problem happens when I try to display images from within the ITEM controller's show function. I haven't been able to figure out how to make it work. If i copy ItemImage controller show section into item controller's show function I will get an error saying "Property [id] does not exist on this collection instance."

    public function show(Item $item)
    {
    $item=Item::findOrFail($item);
    $imageGalleries=ItemImage::where('item_id',$item)->get();
    //dd($imageGalleries);
    return view('admin.itemview',compact('item','imageGalleries'));
    }

Basically I think I didn't fully understand how to use Eloquent properly. Could someone please help me understand where my error is?

I was just able to do it but using Query builder instead. The following displays images correctly within the item controller. I'm starting to think I shouldn't waste any more time on Eloquent and develop everything with the Query builder. I know MYSQL syntax pretty well and it seems that the Query Builder offers more flexibility and it also offers better performance.

    public function show(Item $item)
    {
    // Gets a list of all images for a particular image from database.
    $imageGalleries = DB::table('itemimages')
    ->where('item_id', $item->id)
    ->get();
    return view('admin.itemview',compact('item','imageGalleries'));
    }
0 likes
2 replies
floxn's avatar
floxn
Best Answer
Level 50

Just use the relations you already created:

public function show(Item $item)
{
    $photos = $item->itemphotos;

    return view('admin.itemview', compact('item', 'photos');
}

Or just lazy eager load the relation and grab it from the model inside the view:

public function show(Item $item)
{
    $item->load('itemphotos');

    return view('admin.itemview', compact('item');
}
1 like
Triumfator's avatar

Thank you for your help Floxn. That works. I'll keep developing my little project and I'll see whether i'll go with Eloquent or Query builder. So far I'm leaning towards Query builder because it offers higher performance than Eloquent.

Found a great research paper comparing performance of Eloquent and Query builder...

Comparison of performance between RawSQL and Eloquent ORM in Laravel. Definitely a good read. http://www.diva-portal.org/smash/get/diva2:1014983/FULLTEXT02

Please or to participate in this conversation.