---
title: "Model resolution — Package Toolkit for Laravel | Roundly"
description: "Resolve a configurable Eloquent model class with ModelResolver or ResolvesModels — a class not extending the packaged model throws."
url: https://roundly-consulting.com/open-source/docs/package-toolkit-for-laravel/model-resolution
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Package Toolkit for Laravel](https://roundly-consulting.com/open-source/docs/package-toolkit-for-laravel.md)

# Model resolution

Packages let hosts swap their models through config('<package>.models.\*'). ModelResolver::for(string $key, ?string $default = null, ?string $base = null) does the resolve-and-validate dance once: the default applies only when the key is not set (absent, null or blank — '' or whitespace), and the class must exist, be an Eloquent model, and be $base or a subclass of it. $base defaults to $default — the packaged model a host extends — else to Model. Anything else throws InvalidConfigurationException naming the key; a wrong class never silently falls back to the packaged one:

```php
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\PackageToolkit\Support\ModelResolver;

// Resolve + validate a model class from config: absent or blank → the packaged default; anything
// that isn't that class or a subclass of it throws (never a silent fall-back).
$class = ModelResolver::for('comments.models.comment', Comment::class);       // class-string<Comment>
$model = ModelResolver::newModel('comments.models.comment', Comment::class);  // a fresh instance

// The default is only a suggestion here — a host may name any Eloquent model:
$tenant = ModelResolver::for('comments.models.tenant', Team::class, base: Model::class);

// No default: the key is required, and any Eloquent model is accepted.
$class = ModelResolver::for('comments.models.comment');
```

Pass base: Model::class when the default is only a suggestion a host may replace with an unrelated model. newModel() takes the same arguments and returns a fresh instance of the resolved class. A host model that does not extend the packaged one — or a class name that does not exist — fails like this:

```php
// config('comments.models.comment') === App\Models\Post::class — not a Comment
ModelResolver::for('comments.models.comment', Comment::class);
// throws InvalidConfigurationException:
// Configuration value [comments.models.comment] must be a class-string of [<Comment's class>], [App\Models\Post] given.

// config('comments.models.comment') === 'App\Nope' — no such class
// throws the same message, with [App\Nope] given.
```

## The ResolvesModels trait

For classes that resolve several models from config, the ResolvesModels trait wraps ModelResolver in two protected methods — modelClass() and newModel() — each taking the same optional $default and $base, with the same rules:

```php
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\PackageToolkit\Concerns\ResolvesModels;

final class CommentRepository
{
    use ResolvesModels;

    public function create(array $attributes): Model
    {
        $comment = $this->newModel('comments.models.comment', Comment::class);
        $comment->fill($attributes)->save();

        return $comment;
    }

    public function find(int|string $id): ?Model
    {
        return $this->modelClass('comments.models.comment', Comment::class)::query()->find($id);
    }
}
```

observesModel() on the base provider resolves through the same validator — see Bindings & observers.

## Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

[More ways to support, including crypto](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/package-toolkit-for-laravel.md)
