PHPackages                             hamid09430/direct-nested-relation-object - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Database &amp; ORM](/categories/database)
4. /
5. hamid09430/direct-nested-relation-object

ActiveLibrary[Database &amp; ORM](/categories/database)

hamid09430/direct-nested-relation-object
========================================

Laravel Eloquent HasManyThrough relationship with unlimited levels

2.2(7y ago)08MITPHPPHP &gt;=7.0

Since Jan 24Pushed 7y agoCompare

[ Source](https://github.com/hamid09430/Direct-Nested-Relation-Object)[ Packagist](https://packagist.org/packages/hamid09430/direct-nested-relation-object)[ RSS](/packages/hamid09430-direct-nested-relation-object/feed)WikiDiscussions master Synced 3d ago

READMEChangelog (2)Dependencies (2)Versions (3)Used By (0)

[![Build Status](https://camo.githubusercontent.com/18794261808efa57e2a1ad45e75720e8d81fa8fce4fa8b29b7a4bf40e2ea71e7/68747470733a2f2f7472617669732d63692e6f72672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702e7376673f6272616e63683d6d6173746572)](https://travis-ci.org/staudenmeir/eloquent-has-many-deep)[![Code Coverage](https://camo.githubusercontent.com/d24dfa384db4fafaf1ec3463e7855a7e5a009af21270355101b231fa0e02d0c6/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f6261646765732f636f7665726167652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/staudenmeir/eloquent-has-many-deep/?branch=master)[![Scrutinizer Code Quality](https://camo.githubusercontent.com/3c4909eff44e7a391a1a9443e4ca03a86722c39ab0b792c72433d2d0be20360f/68747470733a2f2f7363727574696e697a65722d63692e636f6d2f672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f6261646765732f7175616c6974792d73636f72652e706e673f623d6d6173746572)](https://scrutinizer-ci.com/g/staudenmeir/eloquent-has-many-deep/?branch=master)[![Latest Stable Version](https://camo.githubusercontent.com/d74d34d0697797ef953cbb7154fbd4af41081bb3e8a7299f7308e719e38d3e63/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f762f737461626c65)](https://packagist.org/packages/staudenmeir/eloquent-has-many-deep)[![Total Downloads](https://camo.githubusercontent.com/26783768c823e58afce42d8929a9c3dc59b81f9fdcf90692dacd48329137c4d2/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f646f776e6c6f616473)](https://packagist.org/packages/staudenmeir/eloquent-has-many-deep)[![License](https://camo.githubusercontent.com/3245ee1f73111c41d6352d38859ff61fdc85828e63040f7855f4410106f0dcc3/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f6c6963656e7365)](https://packagist.org/packages/staudenmeir/eloquent-has-many-deep)

Introduction
------------

[](#introduction)

This extended version of `HasManyThrough` allows relationships with unlimited intermediate models.
It supports [many-to-many](#belongstomany) and [polymorphic](#morphmany) relationships and all their possible combinations.
Supports Laravel 5.5.29+.

Installation
------------

[](#installation)

```
composer require hamid09430/direct-nested-relation-object:1.1

```

Usage
-----

[](#usage)

- [HasMany](#hasmany)
- [BelongsToMany](#belongstomany)
- [MorphMany](#morphmany)
- [MorphToMany](#morphtomany)
- [MorphedByMany](#morphedbymany)
- [BelongsTo](#belongsto)
- [Existing Relationships](#existing-relationships)
- [HasOneDeep](#hasonedeep)
- [Intermediate and Pivot Data](#intermediate-and-pivot-data)
- [Table Aliases](#table-aliases)
- [Soft Deleting](#soft-deleting)

### HasMany

[](#hasmany)

Using the [documentation example](https://laravel.com/docs/eloquent-relationships#has-many-through) with an additional level:
`Country` → has many → `User` → has many → `Post` → has many → `Comment`

```
class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post']);
    }
}
```

Just like with `hasManyThrough()`, the first argument of `hasManyDeep()` is the related model. The second argument is an array of intermediate models, from the far parent (the model where the relationship is defined) to the related model.

By default, `hasManyDeep()` uses the Eloquent conventions for foreign and local keys. You can also specify custom foreign keys as the third argument and custom local keys as the fourth argument:

```
class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep(
            'App\Comment',
            ['App\User', 'App\Post'], // Intermediate models, beginning at the far parent (Country).
            [
               'country_id', // Foreign key on the "users" table.
               'user_id',    // Foreign key on the "posts" table.
               'post_id'     // Foreign key on the "comments" table.
            ],
            [
              'id', // Local key on the "countries" table.
              'id', // Local key on the "users" table.
              'id'  // Local key on the "posts" table.
            ]
        );
    }
}
```

You can use `null` placeholders for the default keys:

```
class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post'], [null, 'custom_user_id']);
    }
}
```

### BelongsToMany

[](#belongstomany)

You can include `BelongsToMany` relationships in the intermediate path.

Using the [documentation example](https://laravel.com/docs/eloquent-relationships#many-to-many) with an additional level:
`User` → belongs to many → `Role` → has many → `Permission`

Add the pivot table to the intermediate models:

```
class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function permissions()
    {
        return $this->hasManyDeep('App\Permission', ['role_user', 'App\Role']);
    }
}
```

If you specify custom keys, remember to swap the foreign and local key on the "right" side of the pivot table:

```
class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function permissions()
    {
        return $this->hasManyDeep(
            'App\Permission',
            ['role_user', 'App\Role'], // Intermediate models and tables, beginning at the far parent (User).
            [
               'user_id', // Foreign key on the "role_user" table.
               'id',      // Foreign key on the "roles" table (local key).
               'role_id'  // Foreign key on the "permissions" table.
            ],
            [
              'id',      // Local key on the "users" table.
              'role_id', // Local key on the "role_user" table (foreign key).
              'id'       // Local key on the "roles" table.
            ]
        );
    }
}
```

### MorphMany

[](#morphmany)

You can include `MorphMany` relationships in the intermediate path.

Using the [documentation example](https://laravel.com/docs/eloquent-relationships#polymorphic-relations) with an additional level:
`User` → has many → `Post` → morph many → `Comment`

Specify the polymorphic foreign keys as an array, starting with the `*_type` column:

```
class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postComments()
    {
        return $this->hasManyDeep(
            'App\Comment',
            ['App\Post'],
            [null, ['commentable_type', 'commentable_id']]
        );
    }
}
```

### MorphToMany

[](#morphtomany)

You can include `MorphToMany` relationships in the intermediate path.

Using the [documentation example](https://laravel.com/docs/eloquent-relationships#many-to-many-polymorphic-relations) with an additional level:
`User` → has many → `Post` → morph to many → `Tag`

Add the pivot table to the intermediate models and specify the polymorphic foreign keys as an array, starting with the `*_type` column:

```
class User extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postTags()
    {
        return $this->hasManyDeep(
            'App\Tag',
            ['App\Post', 'taggables'],
            [null, ['taggable_type', 'taggable_id'], 'id'],
            [null, null, 'tag_id']
        );
    }
}
```

Remember to swap the foreign and local key on the "right" side of the pivot table:

### MorphedByMany

[](#morphedbymany)

You can include `MorphedByMany` relationships in the intermediate path.

Using the [documentation example](https://laravel.com/docs/eloquent-relationships#many-to-many-polymorphic-relations) with an additional level:
`Tag` → morphed by many → `Post` → has many → `Comment`

Add the pivot table to the intermediate models and specify the polymorphic local keys as an array, starting with the `*_type` column:

```
class Tag extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postComments()
    {
        return $this->hasManyDeep(
            'App\Comment',
            ['taggables', 'App\Post'],
            [null, 'id'],
            [null, ['taggable_type', 'taggable_id']]
        );
    }
}
```

### BelongsTo

[](#belongsto)

You can include `BelongsTo` relationships in the intermediate path:
`Tag` → morphed by many → `Post` → belongs to → `User`

Swap the foreign and local key:

```
class Tag extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function postAuthors()
    {
        return $this->hasManyDeep(
            'App\User',
            ['taggables', 'App\Post'],
            [null, 'id', 'id'],
            [null, ['taggable_type', 'taggable_id'], 'user_id']
        );
    }
}
```

### Existing Relationships

[](#existing-relationships)

In complex cases, you can define a `HasManyDeep` relationship by chaining existing relationships:

```
class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeepFromRelations($this->posts(), (new Post)->comments());
    }

    public function posts()
    {
        return $this->hasManyThrough('App\Post', 'App\User');
    }
}

class Post extends Model
{
    public function comments()
    {
        return $this->hasMany('App\Comment');
    }
}
```

### HasOneDeep

[](#hasonedeep)

Use the `HasOneDeep` relationship if you only want to retrieve a single related instance:

```
class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function latestComment()
    {
        return $this->hasOneDeep('App\Comment', ['App\User', 'App\Post'])
            ->latest('comments.created_at');
    }
}
```

### Intermediate and Pivot Data

[](#intermediate-and-pivot-data)

Use `withIntermediate()` to retrieve attributes from intermediate tables:

```
public function comments()
{
    return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post'])
        ->withIntermediate('App\Post');
}

foreach ($country->comments as $comment) {
    // $comment->post->title
}
```

By default, this will retrieve all the table's columns. Be aware that this executes a separate query to get the list of columns.

You can specify the selected columns as the second argument:

```
public function comments()
{
    return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post'])
        ->withIntermediate('App\Post', ['id', 'title']);
}
```

As the third argument, you can specify a custom accessor:

```
public function comments()
{
    return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post'])
        ->withIntermediate('App\Post', ['id', 'title'], 'accessor');
}

foreach ($country->comments as $comment) {
    // $comment->accessor->title
}
```

If you retrieve data from multiple tables, you can use nested accessors:

```
public function comments()
{
    return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post'])
        ->withIntermediate('App\Post')
        ->withIntermediate('App\User', ['*'], 'post.user');
}

foreach ($country->comments as $comment) {
    // $comment->post->title
    // $comment->post->user->name
}
```

Use `withPivot()` for the pivot tables of `BelongsToMany` and `MorphToMany`/`MorphedByMany` relationships:

```
public function permissions()
{
    return $this->hasManyDeep('App\Permission', ['role_user', 'App\Role'])
        ->withPivot('role_user', ['expires_at']);
}

foreach ($user->permissions as $permission) {
    // $permission->role_user->expires_at
}
```

You can specify a custom pivot model as the third argument and a custom accessor as the fourth:

```
public function permissions()
{
    return $this->hasManyDeep('App\Permission', ['role_user', 'App\Role'])
        ->withPivot('role_user', ['expires_at'], 'App\RoleUserPivot', 'pivot');
}

foreach ($user->permissions as $permission) {
    // $permission->pivot->expires_at
}
```

### Table Aliases

[](#table-aliases)

If your relationship path contains the same model multiple times, you can specify a table alias:

```
class Post extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function childComments()
    {
        return $this->hasManyDeep('App\Comment', ['App\Comment as alias'], [null, 'parent_id']);
    }
}
```

Use the `HasTableAlias` trait in the models you are aliasing:

```
class Comment extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;
}
```

### Soft Deleting

[](#soft-deleting)

By default, soft-deleted intermediate models will be excluded from the result. Use `withTrashed()` to include them:

```
class Country extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function comments()
    {
        return $this->hasManyDeep('App\Comment', ['App\User', 'App\Post'])
            ->withTrashed('users.deleted_at');
    }
}

class User extends Model
{
    use SoftDeletes;
}
```

###  Health Score

24

—

LowBetter than 32% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity56

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~0 days

Total

2

Last Release

2668d ago

Major Versions

1.1 → 2.22019-01-24

### Community

Maintainers

![](https://www.gravatar.com/avatar/572db8a3c75825ac207902d462bb634437dd6b7ece6eac3fac083d37fd262441?d=identicon)[Hamid09430](/maintainers/Hamid09430)

---

Top Contributors

[![hamid09430](https://avatars.githubusercontent.com/u/32384372?v=4)](https://github.com/hamid09430 "hamid09430 (6 commits)")

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/hamid09430-direct-nested-relation-object/health.svg)

```
[![Health](https://phpackages.com/badges/hamid09430-direct-nested-relation-object/health.svg)](https://phpackages.com/packages/hamid09430-direct-nested-relation-object)
```

###  Alternatives

[owen-it/laravel-auditing

Audit changes of your Eloquent models in Laravel

3.4k33.0M95](/packages/owen-it-laravel-auditing)[staudenmeir/eloquent-json-relations

Laravel Eloquent relationships with JSON keys

1.1k5.8M24](/packages/staudenmeir-eloquent-json-relations)[bavix/laravel-wallet

It's easy to work with a virtual wallet.

1.3k1.1M11](/packages/bavix-laravel-wallet)[dragon-code/migrate-db

Easy data transfer from one database to another

15717.4k](/packages/dragon-code-migrate-db)[gearbox-solutions/eloquent-filemaker

A package for getting FileMaker records as Eloquent models in Laravel

6454.8k2](/packages/gearbox-solutions-eloquent-filemaker)[cybercog/laravel-ownership

Laravel Ownership simplify management of Eloquent model's owner.

9126.6k3](/packages/cybercog-laravel-ownership)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
