Wrong model instance is returned from builder collection
vunguyen-it opened this issue · comments
- Larastan Version: v2.6.4
--level
used: 5- Pull request with failing test:
Description
When retrieving models using the morphToMany
relation, it doesn't return the correct model instance.
It seems not to work correctly with the morphToMany
relationship, other kinds of relation work well.
Laravel code where the issue was found
Relation definition:
/**
* A model may have multiple roles.
*/
public function roles(): BelongsToMany
{
return $this->morphToMany(
config('permission.models.role'),
'model',
config('permission.table_names.model_has_roles'),
config('permission.column_names.model_morph_key'),
PermissionRegistrar::$pivotRole
);
}
Function having issue:
/**
* Get the role associated with the User
*/
public function getRoleAttribute(): Role | null
{
if ($this->relationLoaded('roles')) {
return $this->roles->first();
}
return $this->roles()->first();
}
Error message:
Method App\Models\User::getRoleAttribute() should return Spatie\Permission\Models\Role|null but returns Illuminate\Database\Eloquent\Model|null.
Please add PHP generics to roles method.
Like @szepeviktor said, it is not possible to statically determine the return type of the roles method. You can help yourself by adding genetic return type.
In my case, the roles method belongs to the 3rd party lib, so I can't modify it. Instead, adding a variable type suggestion like ** @var Type
to the getRoleAttribute
method can help. Here is the code for anyone that interested:
public function getRoleAttribute(): Role | null
{
if ($this->relationLoaded('roles')) {
/** @var Role|null */
return $this->roles->first();
}
/** @var Role|null */
return $this->roles()->first();
}
In my case, the roles method belongs to the 3rd party lib, so I can't modify it.
This is what stubs are for!!