onairmarc's avatar

Model Class Properties

I'm working on implementing Larastan and am running into an issue where the model attributes are not being recognized as class properties. Is there a best practice for allowing for strong typing of model attributes for both Larastan and PhpStorm?

The desired outcome would in effect, be something like this:

class Foo {
  public string $a_string
  public int $an_int

  protected $fillable = [
    'a_string',
    'an_int'
  ]
}

I'm sure there's something that I'm either missing or not understanding, so any advice the community has would be greatly appreciated!

0 likes
1 reply
LaryAI's avatar
Level 58

Laravel models use magic methods to provide access to the attributes that correspond to the columns in the database table. This can cause static analysis tools like Larastan and IDEs like PhpStorm to not recognize these attributes as class properties.

To help these tools understand the properties of your models, you can use PHPDoc blocks to document the model properties. This will not only help static analysis tools but also provide auto-completion support in PhpStorm.

Here's how you can document your model properties using PHPDoc:

/**
 * @property string $a_string
 * @property int $an_int
 */
class Foo extends Model
{
    protected $fillable = [
        'a_string',
        'an_int',
    ];
}

By adding the @property annotations, you're informing the IDE and static analysis tools about the existence of these properties, even though they are not explicitly defined in the class.

If you want to ensure that these properties are always present and avoid using magic properties, you could use actual typed properties in combination with accessor and mutator methods. However, this approach requires more boilerplate code:

class Foo extends Model
{
    public string $a_string;
    public int $an_int;

    protected $fillable = [
        'a_string',
        'an_int',
    ];

    public function getAStringAttribute(): string
    {
        return $this->attributes['a_string'] ?? '';
    }

    public function setAStringAttribute(string $value): void
    {
        $this->attributes['a_string'] = $value;
    }

    public function getAnIntAttribute(): int
    {
        return $this->attributes['an_int'] ?? 0;
    }

    public function setAnIntAttribute(int $value): void
    {
        $this->attributes['an_int'] = $value;
    }
}

This approach is not commonly used because it's more verbose and goes against the "magic" that Eloquent provides for attribute access. However, it does give you strong typing and property visibility.

For most cases, using PHPDoc blocks is the preferred way to help your tools understand your Eloquent model attributes.

1 like

Please or to participate in this conversation.