Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

TzuSun67's avatar

File upload for 3 product images

Hi All,

I have recently began working on uploading images to my site. This is my first time doing this so not sure what I can do fully or not. I followed a tutorial on youtube to get it working for my auth user however now I am trying to get it working for my products but it is giving this error.

Call to a member function getClientOriginalExtension() on null

form

@extends('layouts.app')
@section('page_title')
    Create Product
@endsection
@section('page_heading')
    <h2>Create Product</h2>
@endsection
@section('content')
<div class="header">Create a Product</div>
    <form class="form" action="/product/{product}/create" enctype="multipart/form-data" method="POST">
        <fieldset>
            @csrf
            <div class="notification is-warning">
                <ul>
                    @error('make')<li>{{ $message }}</li>@enderror
                    @error('model')<li>{{ $message }}</li>@enderror
                    @error('watt')<li>{{ $message }}</li>@enderror
                    @error('genre')<li>{{ $message }}</li>@enderror
                    @error('description')<li>{{ $message }}</li>@enderror
                    @error('star_rating')<li>{{ $message }}</li>@enderror
                    @error('image_1')<li>{{ $message }}</li>@enderror
                    @error('image_2')<li>{{ $message }}</li>@enderror
                    @error('image_3')<li>{{ $message }}</li>@enderror
                </ul>
            </div>
            <div class="holder">
                <label class="left-form" for="make">Make</label>
                <input class="right-form" id="make" name="make" class="input" type="text" placeholder="" autofocus>
            </div>
            <div class="holder">
                <label class="left-form" for="model">Model</label>
                <input class="right-form" id="model" name="model" class="input" type="text" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="watt">Watt</label>
                <input class="right-form" id="watt" name="watt" class="input" type="text" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="genre">Genre</label>
                <input class="right-form" id="genre" name="genre" class="input" type="text" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="description">Description</label>
                <input class="right-form" id="description" name="description" class="input" type="text" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="star_rating">Star Rating</label>
                <input class="right-form" id="star_rating" name="star_rating" class="input" type="text" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="image_1">Image One</label>
                <input class="right-form" id="image_1" name="image_1" class="input" type="file" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="image_2">Image Two</label>
                <input class="right-form" id="image_2" name="image_2" class="input" type="file" placeholder="">
            </div>
            <div class="holder">
                <label class="left-form" for="image_3">Image Three</label>
                <input class="right-form" id="image_3" name="image_3" class="input" type="file" placeholder="">
            </div>

            <div class="submit">
                <button class="reset-reg" type="submit">Save Your Changes</button>
            </div>
        </fieldset>
    </form>
@endsection

controller

<?php

namespace App\Http\Controllers;

use App\Product;
use Illuminate\Http\Request;

class ProductsController extends Controller
{
    public function __construct()
    {
        $this -> middleware('auth')->except('index','show');
    }

    const RULES = [
        'make' => 'required|min:1|max:64',
        'model' => 'required|min:1|max:256',
        'watt' => 'required|min:1|max:256',
        'genre' => 'required|min:1|max:256',
        'description' => 'required|min:1|max:256',
        'star_rating' => 'required|min:1|max:256',
        'image_1' => 'required|image|mimes:jpg,jpeg,bmp,svg,png|max:5000',
        'image_2' => 'required|image|mimes:jpg,jpeg,bmp,svg,png|max:5000',
        'image_3' => 'required|image|mimes:jpg,jpeg,bmp,svg,png|max:5000',
    ];

    const MESSAGES = [
        'make.required' => 'The make of Amplifier is required.',
        'model.required' => 'The model has to have a value.',
        'watt.required' => 'The input field but be an integer.',
        'genre.required' => 'The Amplifier must have a genre.',
        'description.required' => 'The you must give a brief description of the amplifier.',
        'star_rating.required' => 'Please choose a star rating for the product.',
        'image_1.required' => 'You need to have 3 images for a product.',
        'image_2.required' => 'You need to have 3 images for a product.',
        'image_3.required' => 'You need to have 3 images for a product.',
    ];

    const PRODUCTS_PER_PAGE = 5;

    public function index (){
        $products = Product::paginate(self::PRODUCTS_PER_PAGE);
        return view ('product.products') -> with (['products' => $products]);
    }

    public function edit(Request $request, Product $product)
    {
        $product -> update (request (['product']));
        return view ('product.edit') -> with (['product' => $product]);

    }

    public function update (Request $request, Product $product)
    {
        $request -> validate (self::RULES, self::MESSAGES);
        $product -> update ($request -> only('make','model','watt','genre','updated_at','star_rating','description'));
        return redirect () -> action ('ProductsController@index');
    }

    public function create(Request $request){
        return view ('product.create');
    }

    public function store (Request $request){
        if(request()->has('image_1')){
            $productimageone = request()->file('image_1');
            $productimageonename = time() .'.'. $productimageone -> getClientOriginalExtension();
            $prodimgsaveone = public_path('/uploads/avatars/');
            $productimageone -> move($prodimgsaveone, $productimageonename);
            if(request()->has('image_2')){
                $productimagetwo = request() -> file ('image_2');
                $productimagetwoname = time() .'.'.$productimagetwo -> getClientOriginalExtension();
                $prodimgsavetwo = public_path('/uploads/products/');
                $productimagetwo -> move($prodimgsavetwo, $productimagetwoname);
                if(request()->has('image_3')){
                    $productimagethree = request() -> file ('image_3');
                    $productimagethreename = time() .'.'.$productimagethree -> getClientOriginalExtension();
                    $prodimgsavethree = public_path('/uploads/products/');
                    $productimagethree -> move($prodimgsavethree, $productimagethreename);
        $request -> validate (self::RULES, self::MESSAGES);
        $attributes  = request (['make','model','watt','genre', 'description','star_rating','image_1','image_2','image_3']);
        $attributes ['genre_id'] = 0;
        $attributes ['image_1'] = '/uploads/avatars/'.$productimageone;
        $attributes ['image_2'] = '/uploads/avatars/'.$productimagetwo;
        $attributes ['image_3'] = '/uploads/avatars/'.$productimagethree;
        Product::create ($attributes);
        return redirect () -> action ('ProductsController@index');
    }
    }
    }
    }

    public function destroy(Product $product)
    {
        $product -> delete();
        return redirect () -> action ('ProductsController@index');
    }

    public function search (Request $request, Product $product)
    {
        $query = $request -> input ('query');
        $product = Product::where ('make','like',"%$query%")->paginate(self::PRODUCTS_PER_PAGE);
        return view('product.search') -> with ('product', $product);
    }

}

model

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $fillable = [
        'make',
        'model',
        'watt',
        'genre',
        'updated_at',
        'description',
        'star_rating',
        'image_1',
        'image_2',
        'image_3',
    ];

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

Any help on this would greatly appreciated.

Thank you for looking, Ben :)

0 likes
8 replies
Snapey's avatar
  1. move your validation to before storing images

  2. change move() to storeAs

  3. you don't handle images on update method?

  4. simplify your code by un-nesting the ifs and extract the common operations to a function

1 like
TzuSun67's avatar

Hi Snapey,

I have moved my validation now and it now uploads the image to database but as a tmp file.

/uploads/products/C:\XAMPP\tmp\php6D3E.tmp

when doing this with my profile image upload it works fine and gives me this as an output

/uploads/avatars/1585497738.jpg

Any idea why this is?

I also tried using the storeAs function like you suggested however it gave me this error.

League\Flysystem\ExceptionImpossible to create the root directory

Is this because it is wanting to save things into the storage directory instead of saving straight into the public folder?

Thanks for your quick reply to my intial post.

TzuSun67's avatar

Today I tried to edit my code to work with the storeAs function however I am now getting this error.

Impossible to create the root directory "C:\XAMPP\htdocs\Term_One_Assignment_Benjamin_Robinson_U1655703\storage\app\C:/XAMPP/htdocs/Term_One_Assignment_Benjamin_Robinson_U1655703/public/uploads/products".

    if(request()->has('image_1')){
        $productimageone = request()->file('image_1');
        $productimageonename = time() .'.'. $productimageone -> getClientOriginalExtension();
        $prodimgsaveone = public_path('/uploads/products/');
        $productimageone -> storeAs($prodimgsaveone, $productimageonename);

Any idea what this means? I have checked the storage directory and it does have some files in there. But not 100% sure what it is doing. I have asked other people on my web course about this and they don't know either as they haven't come across it before.

Thank you for looking.

TzuSun67's avatar

Hi,

Sorry it has taken so long to get back to you, had lots to do despite with whats going on.

Using the move function was what I used initally but it kept giving a temp file i.e /uploads/products/C:\XAMPP\tmp\php3EC.tmp

Not sure why though as I think I have copied everyhing across from when I made it for the register controller.

Any idea why this could be? Only thing I can think of is me missing something but I can't see anything that I've missed.

Any ideas on this?

TzuSun67's avatar

Hi,

I think a fresh look has fixed my issue the images are now coming through. Just had to change the productimageone to productimageonename

Seems to be working fine now will try it with the other two images before I make this as solved.

TzuSun67's avatar

Update it is now fully working.

Had to add a unique identifier at the end to stop it overwriting itself but all three images are now uploaded successfully thanks everyone for your help on this! :D

Please or to participate in this conversation.