barryvdh/laravel-ide-helper

Attribute accessor/mutator without the counterparts generate wrong model properties

marvinschroeder opened this issue · 1 comments

Versions:

  • ide-helper Version: v3.0.0
  • Laravel Version: v10.46.0
  • PHP Version: 8.1.27

Description:

We have a User model including a users table with a column email.
On the User model we only have a mutator which trims and lowercases the value of the email attribute. There is no accessor (get) defined.
Beginning with v3.0.0 of the ide-helper the property is generated with @property-write string $email. But this should be @property string $email.
This applies also to the other way. If we define just an accessor (get) the property is written as @property-read string $email instead of @property string $email

Steps To Reproduce:

Add a attribute mutator to a model without defining the accessor (get).
The other way: add a attribute accessor to a model without defining the mutator (set).

To add a little more information to that issue, as we are having the same one, this is what should be generated:

  • If Attribute::get defined + existing corresponding DB column : @property
  • If Attribute::get defined + no corresponding DB column : @property-read
  • If Attribute::set defined + existing corresponding DB column : @property
  • If Attribute::set defined + no corresponding DB column : @property-write
  • If Attribute::get defined : @property

PHPStan is indeed complaining that we are using a write-only property whereas it used to be fine.

Code to reproduce

class User extends Model {

    // Assuming we have a DB column `name`

    protected function name(): Attribute {
        return Attribute::get(fn($value) => Str::upper($value));
    }

    protected function randomName(): Attribute {
        return Attribute::get(fn() => Str::random());
    }

    public function resetName(): void {
        $this->name = '';
    }
}

In that case, @property-read $name is generated, whereas it should be @property $name.

Note that @property-read $random_name is generated, and that is correct, as no column is there to back it. Hence $user->random_name = 'something' would indeed be incorrect.