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)