Feature: Eloquent Relation Types
Illuminate\Database\Eloquent\Relations have type support
Background:
Given I have the following config
"""
"""
And I have the following code preamble
"""
*/
public function getPhoneRelationship(User $user): HasOne {
return $user->phone();
}
/**
* @psalm-return BelongsTo
*/
public function getUserRelationship(Phone $phone): BelongsTo {
return $phone->user();
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Models can declare one to many relationships
Given I have the following code
"""
final class Repository
{
/**
* @psalm-return BelongsTo
*/
public function getPostRelationship(Comment $comment): BelongsTo {
return $comment->post();
}
/**
* @psalm-return HasMany
*/
public function getCommentsRelationship(Post $post): HasMany {
return $post->comments();
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Models can declare many to many relationships
Given I have the following code
"""
final class Repository
{
/**
* @psalm-return BelongsToMany
*/
public function getRolesRelationship(User $user): BelongsToMany {
return $user->roles();
}
/**
* @psalm-return BelongsToMany
*/
public function getUserRelationship(Role $role): BelongsToMany {
return $role->users();
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Models can declare has through relationships
Given I have the following code
"""
final class Repository
{
/**
* @psalm-return HasManyThrough
*/
public function getCarsAtMechanicRelationship(User $user): HasManyThrough {
return $user->carsAtMechanic();
}
/**
* @psalm-return HasOneThrough
*/
public function getCarsOwner(Mechanic $mechanic): HasOneThrough {
return $mechanic->carOwner();
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Models can declare polymorphic relationships
Given I have the following code
"""
final class Repository
{
public function getPostsImageDynamicProperty(Post $post): Image {
return $post->image;
}
/**
* @todo: support for morphTo dynamic property
* @psalm-return mixed
*/
public function getImageableProperty(Image $image) {
return $image->imageable;
}
/**
* @todo: better support for morphTo relationships
* @psalm-return MorphTo
*/
public function getImageableRelationship(Image $image): MorphTo {
return $image->imageable();
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Models can declare one to many polymorphic relationships
Given I have the following code
"""
final class Repository
{
/**
* @psalm-return MorphMany
*/
public function getCommentsRelation(Video $video): MorphMany {
return $video->comments();
}
/**
* @psalm-return Collection
*/
public function getComments(Video $video): Collection {
return $video->comments;
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Models can declare many to many polymorphic relationships
Given I have the following code
"""
final class Repository
{
/**
* @psalm-return MorphToMany
*/
public function getTagsRelation(Post $post): MorphToMany {
return $post->tags();
}
/**
* @psalm-return Collection
*/
public function getTags(Post $post): Collection {
return $post->tags;
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Polymorphic models can retrieve their inverse relation
Given I have the following code
"""
final class Repository
{
/**
* todo: this should be a union of possible types...
* @psalm-return mixed
*/
public function getCommentable(Comment $comment) {
return $comment->commentable;
}
}
"""
When I run Psalm
Then I see no errors
Scenario: Relationships can be accessed via a property
Given I have the following code
"""
function testGetPhone(User $user): Phone {
return $user->phone;
}
function testGetUser(Phone $phone): User {
return $phone->user;
}
"""
When I run Psalm
Then I see no errors
Scenario: Relationships can be filtered via dynamic property
Given I have the following code
"""
function testFilterRelationshipFromDynamicProperty(User $user): Phone {
return $user->phone->where('active', 1)->firstOrFail();
}
"""
When I run Psalm
Then I see no errors
Scenario: Relationships can be further constrained via method
Given I have the following code
"""
function testFilterRelationshipFromMethod(User $user): Phone {
return $user->phone()->where('active', 1)->firstOrFail();
}
"""
When I run Psalm
Then I see no errors
Scenario: Relationships return themselves when the underlying method returns a builder
Given I have the following code
"""
/**
* @param HasOne $relationship
* @psalm-return HasOne
*/
function testRelationshipsReturnThemselvesInsteadOfBuilders(HasOne $relationship): HasOne {
return $relationship->where('active', 1);
}
/**
* @psalm-return BelongsTo
*/
function testAnother(Phone $phone): BelongsTo {
return $phone->user()->where('active', 1);
}
"""
When I run Psalm
Then I see no errors
Scenario: Relationships return themselves when the proxied method is a query builder method
Given I have the following code
"""
/**
* @param HasOne $relationship
* @psalm-return HasOne
*/
function test(HasOne $relationship): HasOne {
return $relationship->orderBy('id', 'ASC');
}
"""
When I run Psalm
Then I see no errors