DEV Community

Giacomo Masseroni
Giacomo Masseroni

Posted on

PHPDocs for Laravel relationships

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
 ------ -----------------------------------------------------------------------------------------------------------------------------
Enter fullscreen mode Exit fullscreen mode

What happened?
You have a model defined like this:

public function commentable(): MorphTo  
{  
    return $this->morphTo(__FUNCTION__, 'commentable_type', 'commentable_id');  
}
Enter fullscreen mode Exit fullscreen mode

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');  
 }
Enter fullscreen mode Exit fullscreen mode

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');  
}
Enter fullscreen mode Exit fullscreen mode

BelongsTo

/**  
 * @return BelongsTo<Post, $this>  
 */
public function post(): BelongsTo  
{  
    return $this->belongsTo(Post::class, 'id_post');  
}
Enter fullscreen mode Exit fullscreen mode

HasMany

/**  
 * @return HasMany<PostFollowingPost, $this>  
 */
public function postFollowingPostsAsFollowing(): HasMany  
{  
    return $this->hasMany(PostFollowingPost::class, 'following_id', 'id');  
}
Enter fullscreen mode Exit fullscreen mode

HasOneThrough

/**  
 * @return HasOneThrough<Post, Pivot, $this>
 */
public function posts(): HasOneThrough
{  
    return $this->hasOneThrough(Post::class, Pivot::class, 'post_id', 'id');  
}
Enter fullscreen mode Exit fullscreen mode

HasManyThrough

/**  
 * @return HasManyThrough<Post, Pivot, $this> 
 */
public function posts(): HasManyThrough
{  
    return $this->hasManyThrough(Post::class, Pivot::class, 'post_id', 'id');  
}
Enter fullscreen mode Exit fullscreen mode

BelongsToMany

/**  
 * @return BelongsToMany<Post, $this>
 */
public function posts(): BelongsToMany
{  
    return $this->belongsToMany(Post::class, 'post_id', 'id');  
}
Enter fullscreen mode Exit fullscreen mode

MorphTo

/**  
 * @return MorphTo<Model, $this>  
 */
 public function commentable(): MorphTo  
 {  
     return $this->morphTo(__FUNCTION__, 'commentable_type', 'commentable_id');  
 }
Enter fullscreen mode Exit fullscreen mode

MorphOne

/**  
 * @return MorphOne<Post, $this>  
 */
public function post(): MorphOne
{  
    return $this->morphOne(Post::class, 'postable');  
}
Enter fullscreen mode Exit fullscreen mode

MorphMany

/**  
 * @return MorphMany<Post, $this>
 */
public function posts(): MorphMany
{  
    return $this->morphMany(Post::class, 'postable');  
}
Enter fullscreen mode Exit fullscreen mode

MorphToMany

/**  
* @return MorphToMany<Post, $this>  
*/
public function posts(): MorphToMany
{  
    return $this->morphToMany(Post::class, 'name');  
}
Enter fullscreen mode Exit fullscreen mode

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 (0)