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

warpig's avatar
Level 12

Typed property must not be accessed before initialization

I am trying to create a project with 1 or multiple images and a few string fields and I am getting the below error, i need some help spotting what is causing this.

Typed property App\Http\Livewire\ProjectsForm::$project must not be accessed before initialization 

The livewire component

<?php

namespace App\Http\Livewire;

use App\Models\Project;
use Livewire\Component;
use App\Models\ProjectPhoto;
use Livewire\WithFileUploads;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Auth;

class ProjectsForm extends Component
{   
    use WithFileUploads;

    public Project $project;
    public $title;
    public $description;
    public $display_date;
    public $url;
    public $photos = [];
    
    protected $rules = [
        'title' => 'required|min:6',
        'description' => 'required|min:15',
        'display_date' => 'required',
        'url' => 'url|nullable'
    ];

    public function submitForm()
    {
        DB::transaction(function () {
            $this->validate();

            Project::create([
                'user_id' => Auth::user()->id,
                'title' => $this->title,
                'description' => $this->description,
                'display_date' => $this->display_date,
                'url' => $this->url
            ]);

            $this->validate([
                'photos.*' => 'image',
            ]);

            foreach ($this->photos as $photo) {
                $photo->store('projects/photos');
            }

            ProjectPhoto::create([
                'project_id' => $this->project->id,
                'photos' => $this->photos
            ]);

            session()->flash('new_project', 'New project added, nice!');

            return redirect()->to('/projects');
        });
    }

    public function render()
    {
        return view('livewire.projects-form');
    }
}
  1. livewire/projects-form.blade.php
    <form wire:submit.prevent="submitForm">
        @csrf
            <div wire:model="title">
                <input 
                    type="text"
                    name="title"
                    required
                    placeholder="Title"
                >
                    @error('title')
                        <p
                            {{ $errors->first('title') }}
                        </p>
                    @enderror
            </div> <!-- title end -->
            
            <div>
                <div 
                    data-validate="Description is required" 
                >
                    <textarea
                        wire:model="description"
                        name="description"
                        required></textarea>
                        @error('description')
                            <p>
                                {{ $errors->first('description') }}
                            </p>
                        @enderror
                </div> <!-- description end -->
            
                <div>
                    @if ($photos)
                        <div>
                            <label 
                                for="photos"
                            >
                                <span>
                                    <div>
                                        @foreach ($photos as $photo)
                                            <div>
                                                <img src="{{ $photo->temporaryUrl() }}">
                                            </div>
                                        @endforeach <!-- preview images end -->
                                    </div>
                                </span>
                                <input
                                    wire:model="photos"
                                    name="photos"
                                    type="file"
                                    id="photos"
                                    accept="photos/*"
                                    multiple
                                >
                            @error('photos.*') <span class="error">{{ $message }}</span> @enderror
                        </div> <!-- images wrapper end -->
                    @else
                        <div>
                            <label for="photos">
                            <span>
                                <svg/>
                                </svg>
                            </span>
                                <input
                                    wire:model="photos"
                                    name="photos"
                                    type="file"
                                    id="photos"
                                    accept="photos/*"
 
                                    multiple
                                >
                            @error('photos.*') <span class="error">{{ $message }}</span> @enderror
                        </div> <!-- no images yet wrapper end -->
                    @endif
                </div> <!-- images end -->
            
                <div>
                    <div 
                        data-validate="Display date is required" 
                    >
                        <input
                            wire:model="display_date"
                            type="text"
                            name="display_date"
                            required
                            placeholder="Date to display"
                        >
                            @error('display_date')
                                <p>
                                    {{ $errors->first('display_date') }}
                                </p>
                            @enderror
                    </div> <!-- display date end -->
                    
                    <div id="url">
                        <input
                            wire:model="url"
                            type="text"
                            name="url"
                            placeholder="URL http://www.website.com (optional)"
                        >
                            @error('url')
                                <p>
                                    {{ $errors->first('url') }}
                                </p>
                            @enderror
                    </div> <!-- url end -->
            
                    <div>
                        <button>
                            {{ $submitButtonText ?? 'Create Project' }}
                        </button>
                    </div> <!-- submit button end -->
                </div> <!-- date & url end -->
            </div> <!-- desc, date & url end -->
    </form>
  1. Livewire v2.8.2
  2. Laravel v^7.0|^8.0
  3. Browser Firefox
0 likes
3 replies
aleahy's avatar

It doesn't look like you need the $project variable in your component as you don't use it anywhere, and you are redirecting after creating the project.

Why don't you just remove it?

valentin_vranic's avatar

You does not retrieve the newly added project, so it doesn't know which id to take. You could initialize it when you create the new Project.

$this->project = Project::create([
			// props
])

Please or to participate in this conversation.