PHPackages                             staudenmeir/eloquent-has-many-deep - 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. staudenmeir/eloquent-has-many-deep

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

staudenmeir/eloquent-has-many-deep
==================================

Laravel Eloquent HasManyThrough relationships with unlimited levels

v1.22.1(2mo ago)2.9k13.2M—9.9%160[2 issues](https://github.com/staudenmeir/eloquent-has-many-deep/issues)20MITPHPPHP ^8.3CI passing

Since Jun 26Pushed 2mo ago39 watchersCompare

[ Source](https://github.com/staudenmeir/eloquent-has-many-deep)[ Packagist](https://packagist.org/packages/staudenmeir/eloquent-has-many-deep)[ Fund](https://paypal.me/JonasStaudenmeir)[ RSS](/packages/staudenmeir-eloquent-has-many-deep/feed)WikiDiscussions main Synced 1mo ago

READMEChangelog (10)Dependencies (23)Versions (67)Used By (20)

Eloquent HasManyDeep
====================

[](#eloquent-hasmanydeep)

[![CI](https://github.com/staudenmeir/eloquent-has-many-deep/actions/workflows/ci.yml/badge.svg)](https://github.com/staudenmeir/eloquent-has-many-deep/actions/workflows/ci.yml?query=branch%3Amain)[![Code Coverage](https://camo.githubusercontent.com/98411d46871dcfcbf94c6886774b106f1874ad55e95a2c0fffff14d8f9613e67/68747470733a2f2f636f6465636f762e696f2f67682f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f67726170682f62616467652e7376673f746f6b656e3d483539664966346d4736)](https://codecov.io/gh/staudenmeir/eloquent-has-many-deep)[![PHPStan](https://camo.githubusercontent.com/2b1732baa25914ee5ccbeaf42980d671de29700b49e0639e1edc8e66181f6905/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c25323031302d627269676874677265656e2e7376673f7374796c653d666c6174)](https://github.com/staudenmeir/eloquent-has-many-deep/actions/workflows/static-analysis.yml?query=branch%3Amain)[![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/stats)[![License](https://camo.githubusercontent.com/3245ee1f73111c41d6352d38859ff61fdc85828e63040f7855f4410106f0dcc3/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f656c6f7175656e742d6861732d6d616e792d646565702f6c6963656e7365)](https://github.com/staudenmeir/eloquent-has-many-deep/blob/main/LICENSE)

This extended version of `HasManyThrough` allows relationships with unlimited intermediate models.
It supports [many-to-many](#manytomany) and [polymorphic](#morphmany) relationships and all their possible combinations. It also supports some [third-party packages](#third-party-packages).

Supports Laravel 5.5+.

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

[](#installation)

```
composer require staudenmeir/eloquent-has-many-deep:"^1.7"

```

Use this command if you are in PowerShell on Windows (e.g. in VS Code):

```
composer require staudenmeir/eloquent-has-many-deep:"^^^^1.7"

```

Versions
--------

[](#versions)

LaravelPackage13.x1.2212.x1.2111.x1.2010.x1.189.x1.178.x1.147.x1.126.x1.115.81.85.5–5.71.7Usage
-----

[](#usage)

The package offers two ways of defining deep relationships:
You can concatenate [existing relationships](#concatenating-existing-relationships) or specify the intermediate models, foreign and local keys [manually](#defining-relationships-manually).

- [Concatenating Existing Relationships](#concatenating-existing-relationships)
    - [Constraints](#constraints)
    - [Third-Party Packages](#third-party-packages)
- [Defining Relationships Manually](#defining-relationships-manually)
    - [HasMany](#hasmany)
    - [ManyToMany](#manytomany)
    - [MorphMany](#morphmany)
    - [MorphToMany](#morphtomany)
    - [MorphedByMany](#morphedbymany)
    - [BelongsTo](#belongsto)
    - [HasOneDeep](#hasonedeep)
    - [Composite Keys](#composite-keys)
- [Intermediate and Pivot Data](#intermediate-and-pivot-data)
- [Intermediate and Pivot Constraints](#intermediate-and-pivot-constraints)
- [Table Aliases](#table-aliases)
- [Soft Deleting](#soft-deleting)
- [Getting Unique Results](#getting-unique-results)
- [Reversing Relationships](#reversing-relationships)
- [IDE Helper](#ide-helper)

### Concatenating Existing Relationships

[](#concatenating-existing-relationships)

Consider this [example](https://laravel.com/docs/eloquent-relationships#has-many-through) 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

[](#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)`

#### Third-Party Packages

[](#third-party-packages)

Besides native Laravel relationships, you can also concatenate relationships from these third-party packages:

- : `HasManyMerged`
- : `BelongsToJson`, `HasManyJson`, `HasManyThroughJson`
- : [Tree](https://github.com/staudenmeir/laravel-adjacency-list?tab=readme-ov-file#deep-relationship-concatenation)&amp; [Graph](https://github.com/staudenmeir/laravel-adjacency-list?tab=readme-ov-file#graphs-deep-relationship-concatenation)relationships
- : `BelongsTo`, `HasMany`, `HasOne`

### Defining Relationships Manually

[](#defining-relationships-manually)

If you don't have all the necessary existing relationships to concatenate them, you can also define a deep relationship manually by specifying the intermediate models, foreign and local keys.

#### HasMany

[](#hasmany)

Consider this [example](https://laravel.com/docs/eloquent-relationships#has-many-through) from the Laravel documentation 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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class]);
    }
}
```

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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            Comment::class,
            [User::class, Post::class], // 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 default keys:

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

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

#### ManyToMany

[](#manytomany)

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

##### ManyToMany → HasMany

[](#manytomany--hasmany)

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

Add the pivot tables to the intermediate models:

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

    public function permissions(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Permission::class, ['role_user', Role::class]);
    }
}
```

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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            Permission::class,
            ['role_user', Role::class], // 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.
            ]
        );
    }
}
```

##### ManyToMany → ManyToMany

[](#manytomany--manytomany)

Consider this [example](https://laravel.com/docs/eloquent-relationships#many-to-many) from the Laravel documentation with an additional `ManyToMany` level:
`User` → many to many → `Role` → many to many → `Permission`

Add the pivot table to the intermediate models:

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

    public function permissions(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Permission::class, ['role_user', Role::class, 'permission_role']);
    }
}
```

#### MorphMany

[](#morphmany)

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

Consider this [example](https://laravel.com/docs/eloquent-relationships#polymorphic-relations) from the Laravel documentation 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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            Comment::class,
            [Post::class],
            [null, ['commentable_type', 'commentable_id']]
        );
    }
}
```

#### MorphToMany

[](#morphtomany)

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

Consider this [example](https://laravel.com/docs/eloquent-relationships#many-to-many-polymorphic-relations) from the Laravel documentation 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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            Tag::class,
            [Post::class, '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.

Consider this [example](https://laravel.com/docs/eloquent-relationships#many-to-many-polymorphic-relations) from the Laravel documentation 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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            Comment::class,
            ['taggables', Post::class],
            [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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            User::class,
            ['taggables', Post::class],
            [null, 'id', 'id'],
            [null, ['taggable_type', 'taggable_id'], 'user_id']
        );
    }
}
```

#### HasOneDeep

[](#hasonedeep)

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

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

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

#### Composite Keys

[](#composite-keys)

If multiple columns need to match between two tables, you can define a composite key with the `CompositeKey` class.

Consider this [example](https://github.com/topclaudy/compoships#example) from the `compoships` documentation with an additional level:
`User` → has many (matching `team_id` &amp; `category_id`) → `Task` → belongs to → `Project`

```
use Staudenmeir\EloquentHasManyDeep\Eloquent\CompositeKey;

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

    public function projects(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(
            Project::class,
            [Task::class],
            [new CompositeKey('team_id', 'category_id'), 'id'],
            [new CompositeKey('team_id', 'category_id'), 'project_id']
        );
    }
}
```

### Intermediate and Pivot Data

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

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

```
public function comments(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class);
}

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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class, ['id', 'title']);
}
```

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

```
public function comments(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class, ['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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
    return $this->hasManyDeep(Comment::class, [User::class, Post::class])
        ->withIntermediate(Post::class)
        ->withIntermediate(User::class, ['*'], '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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
    return $this->hasManyDeep(Permission::class, ['role_user', Role::class])
        ->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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
{
    return $this->hasManyDeep(Permission::class, ['role_user', Role::class])
        ->withPivot('role_user', ['expires_at'], RoleUser::class, 'pivot');
}

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

### Intermediate and Pivot Constraints

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

You can apply constraints on intermediate and pivot tables:

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

    public function comments(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class]);
    }
}

$commentsFromActiveUsers = $country->comments()->where('users.active', true)->get();
```

### 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 commentReplies(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Comment::class, [Comment::class . ' as alias'], [null, 'parent_id']);
    }
}
```

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

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

For pivot tables, this requires custom models:

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

    public function permissions(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Permission::class, [RoleUser::class . ' as alias', Role::class]);
    }
}

class RoleUser extends Pivot
{
    use \Staudenmeir\EloquentHasManyDeep\HasTableAlias;
}
```

Use `setAlias()` to specify a table alias when concatenating existing relationships:

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

    public function commentReplies(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeepFromRelations(
            $this->comments(),
            (new Comment())->setAlias('alias')->replies()
        );
    }

    public function comments()
    {
        return $this->hasMany(Comment::class);
    }
}

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

    public function replies()
    {
        return $this->hasMany(self::class, 'parent_id');
    }
}
```

### 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(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class])
            ->withTrashed('users.deleted_at');
    }
}

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

### Getting Unique Results

[](#getting-unique-results)

Deep relationships with many-to-many segments can contain duplicate models in their results. If you want to get unique results, you can remove duplicates from the result collection:

```
$uniqueComments = Country::find($id)->comments()->get()->unique();
```

If you need to remove duplicates in the query (e.g. for pagination), try adding `distinct()`:

```
$uniqueComments = Country::find($id)->comments()->distinct()->get();
```

`distinct()` doesn't work for all cases. If it doesn't work for you, use `groupBy()` instead:

```
$uniqueComments = Country::find($id)->comments()
    ->getQuery()             // Get the underlying query builder
    ->select('comments.*')   // Select only columns from the related table
    ->groupBy('comments.id') // Group by the related table's primary key
    ->get();
```

### Reversing Relationships

[](#reversing-relationships)

You can define a `HasManyDeep`/`HasOneDeep` relationship by reversing an existing deep relationship using `hasManyDeepFromReverse()`/`hasOneDeepFromReverse()`:

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

    public function comments(): \Staudenmeir\EloquentHasManyDeep\HasManyDeep
    {
        return $this->hasManyDeep(Comment::class, [User::class, Post::class]);
    }
}

class Comment extends Model
{
    use \Staudenmeir\EloquentHasManyDeep\HasRelationships;

    public function country(): \Staudenmeir\EloquentHasManyDeep\HasOneDeep
    {
        return $this->hasOneDeepFromReverse(
            (new Country())->comments()
        );
    }
}
```

### IDE Helper

[](#ide-helper)

If you are using [barryvdh/laravel-ide-helper](https://github.com/barryvdh/laravel-ide-helper), this package provides a model hook that will correctly add relations when generating the type hints. The model hook is **enabled by default** using [Package Discovery](https://laravel.com/docs/packages#package-discovery).

To enable it manually, add [model hook](https://github.com/barryvdh/laravel-ide-helper#model-hooks) to the model\_hooks array.

```
    // File: config/ide-helper.php

    /*
    |--------------------------------------------------------------------------
    | Models hooks
    |--------------------------------------------------------------------------
    |
    | Define which hook classes you want to run for models to add custom information
    |
    | Hooks should implement Barryvdh\LaravelIdeHelper\Contracts\ModelHookInterface.
    |
    */

    'model_hooks' => [
        \Staudenmeir\EloquentHasManyDeep\IdeHelper\DeepRelationsHook::class,
    ],
```

To disable the model hook you have 3 options:

- [Disable using .env](#disable-using-env)
- [Disable using config](#disable-using-config)
- [Disable by option out of Package Discovery](#disable-by-opting-out-of-package-discovery)

#### Disable using .env

[](#disable-using-env)

Update your `.env` file to include:

```
ELOQUENT_HAS_MANY_DEEP_IDE_HELPER_ENABLED=false
```

#### Disable using config

[](#disable-using-config)

Publish the config and disable the setting directly:

```
php artisan vendor:publish --tag=eloquent-has-many-deep

```

```
    // File: config/eloquent-has-many-deep.php

    /*
    |--------------------------------------------------------------------------
    | IDE Helper
    |--------------------------------------------------------------------------
    |
    | Automatically register the model hook to receive correct type hints
    |
    */
    'ide_helper_enabled' => false,
```

#### Disable by opting out of Package Discovery

[](#disable-by-opting-out-of-package-discovery)

Update your `composer.json` with the following:

```
"extra": {
    "laravel": {
        "dont-discover": [
            "staudenmeir/eloquent-has-many-deep"
        ]
    }
},
```

Contributing
------------

[](#contributing)

Please see [CONTRIBUTING](.github/CONTRIBUTING.md) and [CODE OF CONDUCT](.github/CODE_OF_CONDUCT.md) for details.

###  Health Score

78

—

ExcellentBetter than 100% of packages

Maintenance87

Actively maintained with recent releases

Popularity74

Solid adoption and visibility

Community42

Growing community involvement

Maturity92

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 94.8% 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 ~46 days

Recently: every ~31 days

Total

62

Last Release

65d ago

PHP version history (12 changes)v1.0PHP &gt;=7.0

v1.8PHP ^7.1.3

v1.9PHP ^7.2

v1.12PHP ^7.2.5

v1.13PHP ^7.3

v1.13.1PHP ^7.3|^8.0

1.12.x-devPHP ^7.2.5|^8.0

1.11.x-devPHP ^7.2|^8.0

v1.15PHP ^8.0.2

v1.18PHP ^8.1

v1.20PHP ^8.2

v1.22PHP ^8.3

### Community

Maintainers

![](https://www.gravatar.com/avatar/3c1c3cda28d147c1899037c3187f89a606ca14f51190de59e88fa91e51647ff6?d=identicon)[staudenmeir](/maintainers/staudenmeir)

---

Top Contributors

[![staudenmeir](https://avatars.githubusercontent.com/u/1853169?v=4)](https://github.com/staudenmeir "staudenmeir (236 commits)")[![hafezdivandari](https://avatars.githubusercontent.com/u/56585913?v=4)](https://github.com/hafezdivandari "hafezdivandari (2 commits)")[![niels-numbers](https://avatars.githubusercontent.com/u/1765602?v=4)](https://github.com/niels-numbers "niels-numbers (2 commits)")[![szepeviktor](https://avatars.githubusercontent.com/u/952007?v=4)](https://github.com/szepeviktor "szepeviktor (2 commits)")[![daniel-de-wit](https://avatars.githubusercontent.com/u/3015394?v=4)](https://github.com/daniel-de-wit "daniel-de-wit (2 commits)")[![thijsdejong](https://avatars.githubusercontent.com/u/25135566?v=4)](https://github.com/thijsdejong "thijsdejong (1 commits)")[![decadence](https://avatars.githubusercontent.com/u/1434668?v=4)](https://github.com/decadence "decadence (1 commits)")[![lidoma](https://avatars.githubusercontent.com/u/2203739?v=4)](https://github.com/lidoma "lidoma (1 commits)")[![mathieutu](https://avatars.githubusercontent.com/u/11351322?v=4)](https://github.com/mathieutu "mathieutu (1 commits)")[![ahoiroman](https://avatars.githubusercontent.com/u/23051150?v=4)](https://github.com/ahoiroman "ahoiroman (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

### Embed Badge

![Health badge](/badges/staudenmeir-eloquent-has-many-deep/health.svg)

```
[![Health](https://phpackages.com/badges/staudenmeir-eloquent-has-many-deep/health.svg)](https://phpackages.com/packages/staudenmeir-eloquent-has-many-deep)
```

###  Alternatives

[staudenmeir/laravel-adjacency-list

Recursive Laravel Eloquent relationships with CTEs

1.5k4.7M27](/packages/staudenmeir-laravel-adjacency-list)[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)

PHPackages © 2026

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