PHPackages                             staudenmeir/belongs-to-through - 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/belongs-to-through

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

staudenmeir/belongs-to-through
==============================

Laravel Eloquent BelongsToThrough relationships

v2.18(2mo ago)1.3k9.3M↓19.3%9618MITPHPPHP ^8.3CI passing

Since Jun 6Pushed 2mo ago18 watchersCompare

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

READMEChangelog (10)Dependencies (14)Versions (45)Used By (18)

BelongsToThrough
================

[](#belongstothrough)

[![CI](https://github.com/staudenmeir/belongs-to-through/actions/workflows/ci.yml/badge.svg)](https://github.com/staudenmeir/belongs-to-through/actions/workflows/ci.yml?query=branch%3Amain)[![Code Coverage](https://camo.githubusercontent.com/97a504717b5c9b25e506e70d1851526b1df19b4da8b52fd8587b7f8d18f60c22/68747470733a2f2f636f6465636f762e696f2f67682f7374617564656e6d6569722f62656c6f6e67732d746f2d7468726f7567682f67726170682f62616467652e7376673f746f6b656e3d5a344b73635646574945)](https://codecov.io/gh/staudenmeir/belongs-to-through)[![PHPStan](https://camo.githubusercontent.com/2b1732baa25914ee5ccbeaf42980d671de29700b49e0639e1edc8e66181f6905/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5048505374616e2d6c6576656c25323031302d627269676874677265656e2e7376673f7374796c653d666c6174)](https://github.com/staudenmeir/belongs-to-through/actions/workflows/static-analysis.yml?query=branch%3Amain)[![Latest Stable Version](https://camo.githubusercontent.com/32821d56709029a38f120362073f84aaabb6767b67a53febd750700b7cfbbc25/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f62656c6f6e67732d746f2d7468726f7567682f762f737461626c65)](https://packagist.org/packages/staudenmeir/belongs-to-through)[![Total Downloads](https://camo.githubusercontent.com/eb354b75cce9173bf74f98c6f76a9cdb0351f2e879d0a87b39ed79134dff39c6/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f62656c6f6e67732d746f2d7468726f7567682f646f776e6c6f616473)](https://packagist.org/packages/staudenmeir/belongs-to-through/stats)[![License](https://camo.githubusercontent.com/4ac69109763879758117d403c239af0018390e5fb4f831421b77eab609a39f0e/68747470733a2f2f706f7365722e707567782e6f72672f7374617564656e6d6569722f62656c6f6e67732d746f2d7468726f7567682f6c6963656e7365)](https://github.com/staudenmeir/belongs-to-through/blob/main/LICENSE)

This inverse version of `HasManyThrough` allows `BelongsToThrough` relationships with unlimited intermediate models.

Supports Laravel 5.0+.

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

[](#installation)

```
composer require staudenmeir/belongs-to-through:"^2.5"

```

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

```
composer require staudenmeir/belongs-to-through:"^^^^2.5"

```

Versions
--------

[](#versions)

LaravelPackage13.x2.1812.x2.1711.x2.1610.x2.139.x2.128.x2.117.x2.106.x2.65.x2.5Usage
-----

[](#usage)

- [Custom Foreign Keys](#custom-foreign-keys)
- [Custom Local Keys](#custom-local-keys)
- [Table Aliases](#table-aliases)
- [Soft Deleting](#soft-deleting)

Consider this `HasManyThrough` relationship:
`Country` → has many → `User` → has many → `Post`

```
class Country extends Model
{
    public function posts()
    {
        return $this->hasManyThrough(Post::class, User::class);
    }
}
```

Use the `BelongsToThrough` trait in your model to define the inverse relationship:
`Post` → belongs to → `User` → belongs to → `Country`

```
class Post extends Model
{
    use \Znck\Eloquent\Traits\BelongsToThrough;

    public function country(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(Country::class, User::class);
    }
}
```

You can also define deeper relationships:
`Comment` → belongs to → `Post` → belongs to → `User` → belongs to → `Country`

Supply an array of intermediate models as the second argument, from the related (`Country`) to the parent model (`Comment`):

```
class Comment extends Model
{
    use \Znck\Eloquent\Traits\BelongsToThrough;

    public function country(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(Country::class, [User::class, Post::class]);
    }
}
```

### Custom Foreign Keys

[](#custom-foreign-keys)

You can specify custom foreign keys as the fifth argument:

```
class Comment extends Model
{
    use \Znck\Eloquent\Traits\BelongsToThrough;

    public function country(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(
            Country::class,
            [User::class, Post::class],
            foreignKeyLookup: [User::class => 'custom_user_id']
        );
    }
}
```

### Custom Local Keys

[](#custom-local-keys)

You can specify custom local keys for the relations:

`VendorCustomerAddress` → belongs to → `VendorCustomer` in `VendorCustomerAddress.vendor_customer_id``VendorCustomerAddress` → belongs to → `CustomerAddress` in `VendorCustomerAddress.address_id`

You can access `VendorCustomer` from `CustomerAddress` by the following

```
class CustomerAddress extends Model
{
    use \Znck\Eloquent\Traits\BelongsToThrough;

    public function vendorCustomer(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(
            VendorCustomer::class,
            VendorCustomerAddress::class,
            foreignKeyLookup: [VendorCustomerAddress::class => 'id'],
            localKeyLookup: [VendorCustomerAddress::class => 'address_id'],
        );
    }
}
```

### Table Aliases

[](#table-aliases)

If your relationship path contains the same model multiple times, you can specify a table alias (Laravel 6+):

```
class Comment extends Model
{
    use \Znck\Eloquent\Traits\BelongsToThrough;

    public function grandparent(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(
            Comment::class,
            Comment::class . ' as alias',
            foreignKeyLookup: [Comment::class => 'parent_id']
        );
    }
}
```

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

```
class Comment extends Model
{
    use \Znck\Eloquent\Traits\HasTableAlias;
}
```

### Soft Deleting

[](#soft-deleting)

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

```
class Comment extends Model
{
    use \Znck\Eloquent\Traits\BelongsToThrough;

    public function country(): \Znck\Eloquent\Relations\BelongsToThrough
    {
        return $this->belongsToThrough(Country::class, [User::class, Post::class])
            ->withTrashed('users.deleted_at');
    }
}

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

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

[](#contributing)

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

Credits
-------

[](#credits)

- [Rahul Kadyan](https://github.com/znck)
- [Danny Weeks](https://github.com/dannyweeks)
- [All Contributors](../../contributors)

###  Health Score

75

—

ExcellentBetter than 100% of packages

Maintenance85

Actively maintained with recent releases

Popularity70

Solid adoption and visibility

Community38

Small or concentrated contributor base

Maturity91

Battle-tested with a long release history

 Bus Factor1

Top contributor holds 63.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 ~93 days

Total

43

Last Release

79d ago

Major Versions

v1.0.1 → v2.0-alpha2015-10-23

v2.17 → 8.5.x-dev2026-02-08

PHP version history (11 changes)v2.4PHP &gt;=5.6

v2.6PHP ^7.2

v2.10PHP ^7.2.5

v2.11PHP ^7.3

v2.11.1PHP ^7.3|^8.0

2.10.x-devPHP ^7.2.5|^8.0

v2.9.1PHP ^7.2|^8.0

v2.12PHP ^8.0.2

v2.13PHP ^8.1

v2.16PHP ^8.2

v2.18PHP ^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 (127 commits)")[![znck](https://avatars.githubusercontent.com/u/2596484?v=4)](https://github.com/znck "znck (51 commits)")[![dannyweeks](https://avatars.githubusercontent.com/u/4365775?v=4)](https://github.com/dannyweeks "dannyweeks (10 commits)")[![SanderMuller](https://avatars.githubusercontent.com/u/9074391?v=4)](https://github.com/SanderMuller "SanderMuller (2 commits)")[![dennislindsey](https://avatars.githubusercontent.com/u/7014018?v=4)](https://github.com/dennislindsey "dennislindsey (2 commits)")[![axlon](https://avatars.githubusercontent.com/u/3661474?v=4)](https://github.com/axlon "axlon (2 commits)")[![muhammedkamel](https://avatars.githubusercontent.com/u/13101778?v=4)](https://github.com/muhammedkamel "muhammedkamel (1 commits)")[![daniel-de-wit](https://avatars.githubusercontent.com/u/3015394?v=4)](https://github.com/daniel-de-wit "daniel-de-wit (1 commits)")[![andreshg112](https://avatars.githubusercontent.com/u/15859884?v=4)](https://github.com/andreshg112 "andreshg112 (1 commits)")[![szepeviktor](https://avatars.githubusercontent.com/u/952007?v=4)](https://github.com/szepeviktor "szepeviktor (1 commits)")[![wnateg](https://avatars.githubusercontent.com/u/7966535?v=4)](https://github.com/wnateg "wnateg (1 commits)")

###  Code Quality

TestsPHPUnit

Static AnalysisPHPStan

### Embed Badge

![Health badge](/badges/staudenmeir-belongs-to-through/health.svg)

```
[![Health](https://phpackages.com/badges/staudenmeir-belongs-to-through/health.svg)](https://phpackages.com/packages/staudenmeir-belongs-to-through)
```

###  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)
