PHPackages                             mattsplat/dynamic-loading - 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. mattsplat/dynamic-loading

ActiveLibrary

mattsplat/dynamic-loading
=========================

Dynamically load undefined relationships

14PHP

Since Aug 2Pushed 2y ago1 watchersCompare

[ Source](https://github.com/mattsplat/DynamicLoading)[ Packagist](https://packagist.org/packages/mattsplat/dynamic-loading)[ RSS](/packages/mattsplat-dynamic-loading/feed)WikiDiscussions master Synced 6d ago

READMEChangelogDependenciesVersions (1)Used By (0)

DynamicLoading
==============

[](#dynamicloading)

Install
-------

[](#install)

`composer require mattsplat/dynamic-loading`

### Basic usage

[](#basic-usage)

You do not need a foreign key connecting your tables.

```
$collectionOfModels->dynamicLoad(
        'name_of_custom_relation', // this is only defined here and where the data is accessed
        function ($model) {

            return RelatedModel::where('conditions', $model->conditions)->orderBy('condition');

        },

        'relation_key', // Optional if this does not exist it will be created as an alias

        'model_key' // Optional used to match the records back to the model
    );

```

If relation\_key and model\_key are not defined they will be created `model_key: {primary_key} relation_key: {model_name}_{primary_key}`

Examples
--------

[](#examples)

#### Ranks user doesn't have ending with 'r'

[](#ranks-user-doesnt-have-ending-with-r)

Given the following database structure it's easy to add a relation for the current rank but not for ranks not associated with the user.

#### users

[](#users)

- id
- rank\_id

#### ranks

[](#ranks)

- id
- name

```
    /// add r ranks relation that gets all ranks that start with r except the user's current rank
    $users = $users->dynamicLoad(

        'r_ranks',

        fn($m) => Rank::where('name', 'like', '%r')->where('id', '!=', $m->rank_id)
    );

```

This would produce 1 query and add the matching ranks query as a relationship to the the collection of users.

#### result

[](#result)

```
$users[0] => [
        'id' => 1,
        'rank_id' => 5,
        'r_ranks' => [
                0 => [
                    'id' => 6,
                    'name' => 'Performer'

                ],
                1 =>  => [
                    'id' => 8,
                    'name' => 'Racer'

                ]
        ]
]

```

This works by injecting the user\_id in a subselect for each model and combining the subqueries with a union.

#### query produced

[](#query-produced)

```
select * from (select *, 1 as user_id from "ranks" where "name" like '%r' and "id" != 1)
        union select * from (select *, 2 as user_id from "ranks" where "name" like '%r' and "id" != 1)
        union select * from (select *, 3 as user_id from "ranks" where "name" like '%r' and "id" != 1)
        union select * from (select *, 4 as user_id from "ranks" where "name" like '%r' and "id" != 1)

```

Here we have a matching user\_id on logins table but if we only want the latest login we have to return them all with a typical relationship. Instead we can dynamically load the just the latest login for a collection of users using just 1 query.

#### users

[](#users-1)

- id

#### logins

[](#logins)

- id
- created\_at
- user\_id

```
   // get the latest login for user
    $users = $users->dynamicLoad(

        'latest_login',

        fn($m) => Login::where('user_id', '!=', $m->id)->latest()->limit(1)

    );

```

The results would look something like this

```
$users => [
        'id' => 1,
        'latest_login' => [
                0 => [
                    'id' => 6,
                    'created_at' => '2020-01-20 10:10:00'

                ],
        ]
],
[
        'id' => 2,
        'latest_login' => [
                0 => [
                    'id' => 78,
                    'created_at' => '2020-01-25 15:10:00'

                ],
        ]
],

```

###  Health Score

14

—

LowBetter than 2% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity5

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity21

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/f0cf90e7e29acd8663e348763679007428d54b8f7a4062e358b93ee981f1e94d?d=identicon)[mattsplat](/maintainers/mattsplat)

---

Top Contributors

[![mattsplat](https://avatars.githubusercontent.com/u/1675848?v=4)](https://github.com/mattsplat "mattsplat (13 commits)")

### Embed Badge

![Health badge](/badges/mattsplat-dynamic-loading/health.svg)

```
[![Health](https://phpackages.com/badges/mattsplat-dynamic-loading/health.svg)](https://phpackages.com/packages/mattsplat-dynamic-loading)
```

PHPackages © 2026

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