Context
The context: you have a Laravel 10/11/12 project, and you want to use PHPStan.
You use a PHPStan level 6 (or higher), because it's cool! (and you're right about that).
You execute the PHPStan command, and this is one of the error you get:
------ -----------------------------------------------------------------------------------------------------------------------------
Line Models\Base\Comment.php
------ -----------------------------------------------------------------------------------------------------------------------------
82 Method App\Models\Base\Comment::commentable() return type with generic class Illuminate\Database\Eloquent\Relations\MorphTo
does not specify its types: TRelatedModel, TDeclaringModel
🪪 missingType.generics
------ -----------------------------------------------------------------------------------------------------------------------------
What happened?
You have a model defined like this:
public function commentable(): MorphTo
{
return $this->morphTo(__FUNCTION__, 'commentable_type', 'commentable_id');
}
Without PHPDoc, PHPStan is unable to check your code to verify if everything is correct.
How can you fix this?
Add this PHPDoc to the function:
/**
* @return MorphTo<Model, $this>
*/
public function commentable(): MorphTo
{
return $this->morphTo(__FUNCTION__, 'commentable_type', 'commentable_id');
}
Following are all PHPDocs you need to add to Laravel relationships to pass PHPStan level > 6 check.
Laravel Relationships
HasOne
/**
* @return HasOne<PostFollowingPost, $this>
*/
public function postFollowingPostsAsFollowing(): HasOne
{
return $this->hasOne(PostFollowingPost::class, 'following_id', 'id');
}
BelongsTo
/**
* @return BelongsTo<Post, $this>
*/
public function post(): BelongsTo
{
return $this->belongsTo(Post::class, 'id_post');
}
HasMany
/**
* @return HasMany<PostFollowingPost, $this>
*/
public function postFollowingPostsAsFollowing(): HasMany
{
return $this->hasMany(PostFollowingPost::class, 'following_id', 'id');
}
HasOneThrough
/**
* @return HasOneThrough<Post, Pivot, $this>
*/
public function posts(): HasOneThrough
{
return $this->hasOneThrough(Post::class, Pivot::class, 'post_id', 'id');
}
HasManyThrough
/**
* @return HasManyThrough<Post, Pivot, $this>
*/
public function posts(): HasManyThrough
{
return $this->hasManyThrough(Post::class, Pivot::class, 'post_id', 'id');
}
BelongsToMany
/**
* @return BelongsToMany<Post, $this>
*/
public function posts(): BelongsToMany
{
return $this->belongsToMany(Post::class, 'post_id', 'id');
}
MorphTo
/**
* @return MorphTo<Model, $this>
*/
public function commentable(): MorphTo
{
return $this->morphTo(__FUNCTION__, 'commentable_type', 'commentable_id');
}
MorphOne
/**
* @return MorphOne<Post, $this>
*/
public function post(): MorphOne
{
return $this->morphOne(Post::class, 'postable');
}
MorphMany
/**
* @return MorphMany<Post, $this>
*/
public function posts(): MorphMany
{
return $this->morphMany(Post::class, 'postable');
}
MorphToMany
/**
* @return MorphToMany<Post, $this>
*/
public function posts(): MorphToMany
{
return $this->morphToMany(Post::class, 'name');
}
I developed a package to generate Laravel Models from an existing database.
The package generates code PHPStan level max compliant:
https://github.com/giacomomasseron/laravel-models-generator
Top comments (1)
This is info helpful! I've been struggling with PHPStan errors on relationships for weeks. The clear examples for each relationship type make it so easy to implement. Definitely bookmarking this and checking out your package – automatic PHPDoc generation would be a huge time-saver!