We recently started using PHPStan 1.10 at level 6 in a Laravel 10 PHP 8.2 project. It reports a few remaining issues in the following model that I would like to fix.
class ArticlePrice extends Model
{
protected $fillable = ['cost_type_id', 'type', 'type_id', 'amount'];
/**
* @var array<string> $with
*/
protected $with = ['types'];
/**
* @return MorphTo
*/
public function types(): MorphTo
{
return $this->morphTo('types', 'type', 'type_id');
}
/**
* @return string
*/
public function getName(): string
{
if ($this->types) {
return $this->type === Article::class ? $this->types->vdm_code : $this->types->name;
}
return '';
}
}
For the types()
MorphTo it reports:
phpstan: Method App\Models\Environment\CostType\ArticlePrice::types()
return type with generic class Illuminate\Database\Eloquent\Relations\MorphTo
does not specify its types: TRelatedModel, TChildModel
But if I change it into MorphTo<Model, Article|Category>
which reflects the actually models it could return at this point it complains about:
phpstan: Method App\Models\Environment\CostType\ArticlePrice::types() should return
Illuminate\Database\Eloquent\Relations\MorphTo<Illuminate\Database\Eloquent\Model,
App\Models\Shop\Article|App\Models\Shop\Category>
but returns Illuminate\Database\Eloquent\Relations\MorphTo<Illuminate\Database\Eloquent\Model,
App\Models\Environment\CostType\ArticlePrice>.
which is weird to me, since we are in ArticlePrice, this seems nonsensical to me.
It has the exact same complaint when I do <Model, Model>
instead.
The other issue is that it does not understand the content of $types
:
phpstan: Access to an undefined property Illuminate\Database\Eloquent\Model::$name.
phpstan: Access to an undefined property Illuminate\Database\Eloquent\Model::$vdm_code.
I hoped fixing the morphTo issue would fix this as well, since vdm_code
and name
are documented properties of their models. But I fear this would not work, so this might need a different way of fixing the issue.
In short, how can I get PHPStan to understand how my polymorphic relation works, and how do I get it to recognise properties of the polymorphic related models?
I fixed the problem with $types
with a workaround by adding this to the class level docblock:
* @property-read Article|Category|null $types
This makes sure PHPStan understands the types $types
can be, and the properties it can have.
Only downside is now, I can't run ide-helper:models
on this model, this would undo it.
And this is the way I fixed the issue with the MorphTo, though its not a satisfactory solution to me. Since to me it feels like this gives the wrong information about the relation about the possible return types. It does get rid of the PHPStan issue, but I rather have be able to give the correct information.
* @return MorphTo<Model, ArticlePrice>