Skip to content

Relations

Relationship types are read from the relation method's declared return type, so that type has to carry its generic parameters. The class the relation points at is taken from there rather than from the hasMany(Post::class) argument, which means an undocumented relation resolves to the base relation class and the related model is lost. Relation query callbacks and builder-of paths then use Builder<Model> rather than assuming the relation still targets the declaring model.

/** @return BelongsTo<User, $this> */
public function user(): BelongsTo
{
    return $this->belongsTo(User::class);
}

/** @return HasMany<Post, $this> */
public function posts(): HasMany
{
    return $this->hasMany(Post::class);
}

whereHas, whereRelation, and the morph variants type the query callback as the related model's builder, including custom builders. withWhereHas and with() include the relation object as well, and each closure in a builder with() array receives the relation its key names (eager-load-of). See builder-of for the builder-of<User, 'posts'> phpdoc form.