Skip to main content
Back to packages
2,863 GitHub stars

staudenmeir/eloquent-has-many-deep

View on GitHub

Description

This extended version of HasManyThrough allows relationships with unlimited intermediate models.

The package offers two ways of defining deep relationships: You can concatenate existing relationships or specify the intermediate models, foreign and local keys manually.

Concatenating Existing Relationships

Consider this example from the Laravel documentation with an additional level:
Country → has many → User → has many → Post → has many → Comment

You can define a HasManyDeep relationship by concatenating existing relationships:

class Country extends Model
{
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
 
public function comments(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
return $this->hasManyDeepFromRelations($this->posts(), (new Post())->comments());
}
 
public function posts()
{
return $this->hasManyThrough(Post::class, User::class);
}
}
 
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}

Define a HasOneDeep relationship with hasOneDeepFromRelations() if you only want to retrieve a single related instance.

Constraints

By default, constraints from the concatenated relationships are not transferred to the new deep relationship. Use hasManyDeepFromRelationsWithConstraints() with the relationships as callable arrays to apply these constraints:

class Country extends Model
{
use \Staudenmeir\EloquentHasManyDeep\HasRelationships;
 
public function comments(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
return $this->hasManyDeepFromRelationsWithConstraints([$this, 'posts'], [new Post(), 'comments']);
}
 
public function posts()
{
return $this->hasManyThrough(Post::class, User::class)->where('posts.published', true);
}
}
 
class Post extends Model
{
public function comments()
{
return $this->hasMany(Comment::class)->withTrashed();
}
}

Make sure to qualify the constraints' column names if they appear in multiple tables:
->where('posts.published', true) instead of ->where('published', true)

Recent Courses on Laravel Daily

Next.js Basics for Laravel Developers

11 lessons
58 min

Laravel 13 Starter Kit Teams and Customizations

10 lessons
33 min

Queues in Laravel 13

18 lessons
1 h 12 min read