This works in the production environment. However, doesn't work in the local environment.
Mar 22, 2022
5
Level 9
Livewire - File Upload Issue
The file is actually not getting uploaded to the folder. When i place a file in the folder(costing_worksheets) by renaming it as per my requirement the file(image) displays
My livewire component looks like this
<?php
namespace App\Http\Livewire;
use Carbon\Carbon;
use App\Models\Comp;
use App\Models\User;
use App\Models\Company;
use Livewire\Component;
use App\Models\Quotation;
use Livewire\WithFileUploads;
class QuotationForm extends Component
{
use WithFileUploads;
public Quotation $quotation;
public $users;
public $companies;
public $comps;
public $selectedUser = null;
public $selectedCompany = null;
public $photo;
protected function rules()
{
return [
'selectedUser' => 'required',
'selectedCompany' => 'nullable',
'quotation.title' => 'required',
'quotation.date' => 'required',
'quotation.to' => 'required',
'quotation.address' => 'nullable',
'quotation.description' => 'nullable',
'quotation.comp_id' => 'required',
'quotation.delivery' => 'nullable',
'quotation.validity' => 'nullable',
'quotation.costing' => 'nullable',
'quotation.status' => 'required',
'photo' => 'nullable|sometimes|image|max:512',
];
}
protected $validationAttributes = [
'selectedUser' => 'Customer',
'quotation.comp_id' => 'Comp',
'photo' => 'attachment',
];
//For real-time validation
public function updated($propertyName)
{
$this->validateOnly($propertyName);
}
public function updatedSelectedUser()
{
//When a user is selected the companies related to that user should appear
$user_id = $this->selectedUser;
//dd($user_id);
$user = User::findOrFail($user_id);
$this->quotation->to = $user->name;
$this->companies = $user->companies;
$this->selectedCompany = $user->companies->first()->id;
$this->quotation->to = $user->title . " " . $user->first_name . " " . $user->last_name;
}
public function updatedSelectedCompany($company_id)
{
$this->quotation->address = Company::find($company_id)->address;
}
public function mount(Quotation $quotation)
{
//FOR NEW AND EXISTING QUOTATION
$this->quotation = $quotation ?? new Quotation();
$this->users = User::where('is_customer', 1)->orderBy('name', 'ASC')->get();
$this->companies = Company::all();
$this->comps = Comp::all();
//FOR NEW QUOTATION ONLY
if($this->quotation->id == null)
{
$this->quotation->date = Carbon::now()->format('Y-m-d');
$this->quotation->title = 'Quotation';
$this->quotation->description = 'Item :
Qty :
Size :
Paper :
Print :
Each :
Total :';
$this->quotation->status = "Pending";
}
//FOR EXISTING QUOTATION ONLY
else
{
$this->selectedUser = $this->quotation->user_id;
$this->companies = User::find($this->selectedUser)->companies;
$this->selectedCompany = $this->quotation->company->id;
}
}
public function save()
{
//FOR NEW AND EXISTING QUOTATION
$this->validate();
$imageToShow = $this->quotation->photo ?? null;
//FOR NEW QUOTATION
if($this->quotation->id == null)
{
Quotation::create([
'user_id' => $this->selectedUser,
'company_id' => $this->selectedCompany,
'comp_id' => $this->quotation->comp_id,
'comp_address' => Comp::find($this->quotation->comp_id)->address,
'number' => $this->quotation->quotationNumber($this->quotation->comp_id),
'date' => $this->quotation->date,
'title' => $this->quotation->title,
'to' => $this->quotation->to,
'address' => $this->quotation->address,
'description' => $this->quotation->description,
'delivery' => $this->quotation->delivery ?? 0,
'validity' => $this->quotation->validity ?? 0,
'costing' => $this->quotation->costing,
'status' => $this->quotation->status,
]);
return redirect()->route('employees.quotations.edit', Quotation::latest()->first()->id);
}
//FOR EXISTING QUOTATION
else
{
//dd($imageToShow);
$fileName = "QID-" .$this->quotation->id . ".jpg";
$this->quotation->fill([
'user_id' => $this->selectedUser,
'company_id' => $this->selectedCompany,
'comp_id' => $this->quotation->comp_id,
'comp_address' => Comp::find($this->quotation->comp_id)->address,
'number' => $this->quotation->quotationNumber($this->quotation->comp_id, $this->quotation->id),
'date' => $this->quotation->date,
'title' => $this->quotation->title,
'to' => $this->quotation->to,
'address' => $this->quotation->address,
'description' => $this->quotation->description,
'delivery' => $this->quotation->delivery,
'validity' => $this->quotation->validity,
'costing' => $this->quotation->costing,
'status' => $this->quotation->status,
'photo' => $this->photo ? $this->photo->storeAs('costing_worksheets', $fileName, 'public') : $imageToShow,
]);
$this->quotation->save();
return redirect(request()->header('Referer')); //To refresh the page
}
return back();
}
public function render()
{
return view('livewire.quotation-form');
}
}
<div>
<form method="post" wire:submit.prevent="save">
@csrf
<div class="grid grid-cols-1 p-4 xl:grid-cols-12 gap-x-4">
<div class="grid grid-cols-1 xl:col-span-6 xl:grid-cols-12 gap-y-4 gap-x-4">
<div class="col-span-12 xl:col-span-6">
<x-jet-label for="user" value="{{ __('CUSTOMER') }}" class="font-bold text-left" />
<select wire:model="selectedUser"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>Choose a Customer</option>
@foreach($users as $user)
<option value="{{ $user->id }}">{{ $user->name }}</option>
@endforeach
</select>
<x-jet-input-error for="selectedUser" class="mt-2" />
</div>
@if($selectedCompany == null)
<div class="col-span-12 xl:col-span-6">
<x-jet-label for="company" value="{{ __('COMPANY') }}" class="font-bold text-left" />
<select wire:model="selectedCompany" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="" selected>Choose a Company</option>
</select>
<x-jet-input-error for="selectedCompany" class="mt-2" />
</div>
@else
<div class="col-span-12 xl:col-span-6">
<x-jet-label for="company" value="{{ __('COMPANY') }}" class="font-bold text-left" />
<select wire:model="selectedCompany" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
@foreach($companies as $company)
<option value="{{ $company->id }}">{{ $company->name }}</option>
@endforeach
</select>
<x-jet-input-error for="selectedCompany" class="mt-2" />
</div>
@endif
<div class="col-span-12 xl:col-span-12">
<x-jet-label for="title" value="{{ __('title') }}" class="font-bold text-left uppercase" />
<x-jet-input wire:model.lazy="quotation.title" id="title" type="text" class="block w-full mt-1" />
<x-jet-input-error for="quotation.title" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-4">
<x-jet-label for="date" value="{{ __('date') }}" class="font-bold text-left uppercase" />
<x-jet-input wire:model.lazy="quotation.date" id="date" type="date" class="block w-full mt-1" />
<x-jet-input-error for="quotation.date" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-8">
<x-jet-label for="to" value="{{ __('To') }}" class="font-bold text-left" />
<x-jet-input wire:model.lazy="quotation.to" id="to" type="text" class="block w-full mt-1" />
<x-jet-input-error for="quotation.to" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-12">
<x-jet-label for="address" value="{{ __('ADDRESS') }}" class="font-bold text-left" />
<textarea wire:model.lazy="quotation.address" name="address" id="address" cols="100" rows="4" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"></textarea>
<x-jet-input-error for="quotation.address" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-12">
<x-jet-label for="description" value="{{ __('DESCRIPTION') }}" class="font-bold text-left" />
<textarea wire:model.lazy="quotation.description" name="description" id="description" cols="120" rows="7" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"></textarea>
<x-jet-input-error for="quotation.description" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-4">
<x-jet-label for="comp" value="{{ __('COMP') }}" class="font-bold text-left" />
<select wire:model="quotation.comp_id"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="">Select</option>
@foreach($comps as $comp)
<option value="{{ $comp->id }}">{{ $comp->short_name }}</option>
@endforeach
</select>
<x-jet-input-error for="quotation.comp_id" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-2">
<x-jet-label for="delivery" value="{{ __('DELIVERY') }}" class="font-bold text-left" />
<x-jet-input wire:model.lazy="quotation.delivery" id="delivery" type="text" class="block w-full mt-1" />
<x-jet-input-error for="quotation.delivery" class="mt-2" />
</div>
<div class="col-span-12 xl:col-span-2">
<x-jet-label for="validity" value="{{ __('VALIDITY') }}" class="font-bold text-left" />
<x-jet-input wire:model.lazy="quotation.validity" id="validity" type="text" class="block w-full mt-1" />
<x-jet-input-error for="quotation.validity" class="mt-2" />
</div>
<div class="col-span-12 py-6 xl:col-span-4">
<x-success-button class="w-full" type="submit">
{{ $quotation->id ? 'Update' : 'Save' }}
</x-success-button>
</div>
</div>
{{-- @dd($quotation->photo); --}}
<div class="grid grid-cols-1 xl:grid-cols-12 xl:col-span-6">
<div class="grid grid-cols-1 xl:grid-cols-12 xl:col-span-12">
<div class="col-span-12 ">
<x-jet-label for="costing" value="{{ __('COSTING') }}" class="font-bold text-left" />
<textarea wire:model.lazy="quotation.costing" name="costing" id="costing" cols="100" rows="15" class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50"></textarea>
<x-jet-input-error for="quotation.costing" class="mt-2" />
<br>
@if($quotation->id != null)
<p><b class="uppercase">attach costing worksheet</b></p>
<input type="file" wire:model="photo">
@error('photo') <span class="text-red-400 error">{{ $message }}</span> @enderror
@endif
</div>
<div class="col-span-12 mb-5 xl:col-span-6">
<x-jet-label for="status" value="{{ __('STATUS') }}" class="font-bold text-left" />
<select wire:model="quotation.status"
class="block w-full mt-1 border-gray-300 rounded-md shadow-sm focus:border-indigo-300 focus:ring focus:ring-indigo-200 focus:ring-opacity-50">
<option value="Pending">Pending - Costing is Pending</option>
<option value="Completed">Completed - Costing is Completed</option>
<option value="Sent">Sent - Quotation Sent to Customer</option>
<option value="Approved">Approved</option>
</select>
<x-jet-input-error for="quotation.status" class="mt-2" />
</div>
</div>
</div>
</div>
</form>
<hr><hr><hr><hr><hr>
{{-- @dd($quotation->photo) --}}
<div class="grid grid-cols-1 p-4 xl:grid-cols-12 gap-x-4">
<div class="col-span-12 ">
@if ($quotation->photo)
<p><b><u>Costing Worksheet Preview</u></b></p>
<img src="{{ Storage::url($quotation->photo) }}" alt="costing-image">
@endif
</div>
</div>
</div>
Quotation class
..
protected $guarded = [];
Please or to participate in this conversation.