Error : Typed property App\Models\User::$name must not be accessed before initialization
milewski opened this issue · comments
Hi, I have a very simple example like this:
class User extends Model
{
use Fluent;
public string $name;
}
Within tests:
$user = UserFactory::new()->create();
dd($user->name);
Throws an error:
Error : Typed property App\Models\User::$name must not be accessed before initialization
What Laravel version is being used? I just tried the same example, and it worked as expected.
I'm having the same problem.
Versions:
PHP: 8.0.10
laravel/framework: v8.61.0
Edit:
I only get the error when the model has a relation.
I tested it with the following code, and it gave the error:
// database/migrations/2021_09_14_184632_create_cars_table.php
Schema::create('cars', function (Blueprint $table) {
$table->id();
$table->unsignedBigInteger('user_id');
$table->timestamps();
$table->foreign('user_id')->references('id')->on('users');
});
// app/Models/Car.php
namespace App\Models;
use Based\Fluent\Fluent;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
class Car extends Model
{
use Fluent;
public int $user_id;
public User $user;
public function user(): BelongsTo
{
return $this->belongsTo(User::class);
}
}
// php artisan tinker
>>> \App\Models\User::factory(1)->create()
>>> $car = new \App\Models\Car
>>> $car->user_id = \App\Models\User::find(1)->id
>>> $car->save()
>>> $car2 = \App\Models\Car::find(1)
>>> $car2->user
PHP Error: Typed property App\Models\Car::$user must not be accessed before initialization in Psy Shell code on line 1
I can only reproduce this by setting name
to nullable
and removing the name
from the factory.
Do you have any other package that can conflict with this one?
Perhaps, do you have a reproducible example?
I can reproduce this one, but loading the relation instead of lazyloading works.
$car2 = \App\Models\Car::find(1)
$car2->load('user')->user;
// or
$car2 = \App\Models\Car::with('user')->find(1)
$car2->user;
I think, this makes sense since user
is not initialized at this moment and needs to be initialized at some point before you can actually call the property. But that just how PHP works. I'm unsure Fluent can be compatible with LazyLoading.
Uhm I was using this package https://github.com/spatie/data-transfer-object as well when this happened, I will try to hook up this library again on some other project and see if I can find out what is wrong
@devRMA The package doesn't support lazy loading. Unfortunately, there's no way to overload public properties by magic getters and setters, so we can't access relations directly unless they're loaded explicitly.
@milewski Let me know if the issue was resolved. Otherwise, I would love to see a more detailed example.
@devRMA The package doesn't support lazy loading. Unfortunately, there's no way to overload public properties by magic getters and setters, so we can't access relations directly unless they're loaded explicitly.
Thanks for the answer. I think this should be in the README, which only works with eager loading.
@devRMA will note this on README. Thanks!
FYI @lepikhinb this was not noted on README.
It's a huge drawback as MyModel::find(1) is no longer a valid way of doing things.