The error "Trying to access array offset on null" typically occurs when you try to access an array element that doesn't exist. In your case, it seems to be related to the file upload process in Livewire.
Here are a few steps to troubleshoot and fix the issue:
-
Ensure the File Input is Correctly Bound: Make sure the file input is correctly bound to the Livewire property. In your form, you have:
<x-text-input wire:model="file" id="file" class="block mt-1 w-full" type="file"/>This should be fine, but ensure that the
wire:modelis correctly set tofile. -
Check the Property Type: The property
public string $file = '';should be changed topublic $file;because it will hold an instance of the uploaded file, not a string. -
Update the Validation Rule: Ensure that the validation rule matches the property type. You have:
'file' => 'required|mimes:pdf,jpg,png|max:2048',This is correct, but make sure the property type is not causing issues.
-
Store the Uploaded File: In your
savemethod, you are trying to store the file using$this->image->store('invoices', 'public');. However, the property is namedfile, notimage. Update this line to:$filename = $this->file->store('invoices', 'public'); -
Ensure File Uploads are Enabled: Make sure you have included the
WithFileUploadstrait in your component, which you have done correctly.
Here is the updated code for your Livewire component:
namespace App\Livewire\Uploads;
use App\Models\AttestRule;
use App\Models\Invoice;
use Auth;
use Livewire\Component;
use Illuminate\Contracts\View\View;
use Illuminate\Validation\Rule;
use Jantinnerezo\LivewireAlert\LivewireAlert;
use Livewire\WithFileUploads;
class Form extends Component
{
use WithFileUploads;
use LivewireAlert;
public ?Invoice $invoice = null;
public $file; // Change from string to a generic type
public function save()
{
$this->validate();
// Store the file into the folder invoices in public
$filename = $this->file->store('invoices', 'public');
if (is_null($this->invoice)) {
$this->invoice = Invoice::create([
'team_id' => Auth::user()->team_id,
'cb' => Auth::id(),
'ub' => Auth::id(),
'ua' => now(),
'file' => $filename,
]);
}
$this->flash('success', 'Post successfully uploaded');
return redirect()->to('/invoices');
}
public function rules(): array
{
return [
'file' => 'required|mimes:pdf,jpg,png|max:2048',
];
}
public function render(): View
{
return view('livewire.uploads.form');
}
}
And ensure your Blade template remains the same, as it looks correct:
<div>
<div class="py-6">
<div class="mx-auto max-w-7xl sm:px-6 lg:px-8">
<div class="overflow-hidden bg-white shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<div class="flex justify-between items-center">
<div><x-section-header>Upload an invoice</x-section-header></div>
<div class="mb-3">
<x-primary-link :href="route('uploads.all')">
<x-icon-link icon="o-arrow-left"/>Cancel
</x-primary-link>
</div>
</div>
<form wire:submit="save" enctype="multipart/form-data">
@csrf
<div>
<x-input-label for="file" :value="__('Invoice')" />
<x-text-input wire:model="file" id="file" class="block mt-1 w-full" type="file"/>
<x-input-error :messages="$errors->get('file')" class="mt-2" />
</div>
<div class="mt-4">
<x-primary-button type="submit">
<x-icon-link icon="o-circle-stack"/>Save
</x-primary-button>
</div>
</form>
<div wire:loading class="absolute inset-0 bg-white opacity-50"></div>
<div wire:loading.delay>
<div wire:loading.flex class="flex justify-center items-center absolute inset-0">
<x-icon-spinner/>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
@push('js')
@endpush
These changes should resolve the error and allow you to upload files using Livewire.