PHPackages                             hosmelq/laravel-model-preferences - 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. hosmelq/laravel-model-preferences

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

hosmelq/laravel-model-preferences
=================================

Per-model preferences for Laravel with defaults and validation.

v1.0.0(3mo ago)12.3k↓33.3%MITPHPPHP ^8.2CI passing

Since Jul 23Pushed 1mo ago1 watchersCompare

[ Source](https://github.com/hosmelq/laravel-model-preferences)[ Packagist](https://packagist.org/packages/hosmelq/laravel-model-preferences)[ RSS](/packages/hosmelq-laravel-model-preferences/feed)WikiDiscussions main Synced 1mo ago

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

Laravel Model Preferences
=========================

[](#laravel-model-preferences)

Laravel Model Preferences provides a simple, fluent API for storing per-model preferences. You may store preferences in a JSON column or database tables and define defaults and validation rules per model.

Table of Contents
-----------------

[](#table-of-contents)

- [Introduction](#introduction)
- [Installation](#installation)
- [Configuration](#configuration)
    - [Default Store](#default-store)
    - [Store Configuration](#store-configuration)
    - [Environment Variables](#environment-variables)
- [Defining Preferences](#defining-preferences)
    - [The InteractsWithPreferences Trait](#the-interactswithpreferences-trait)
    - [The preferencesConfig Method](#the-preferencesconfig-method)
    - [Defaults](#defaults)
    - [Validation Rules](#validation-rules)
- [Using Preferences](#using-preferences)
    - [Obtaining a Preferences Instance](#obtaining-a-preferences-instance)
    - [Retrieving Preferences](#retrieving-preferences)
    - [Storing Preferences](#storing-preferences)
    - [Checking for Presence](#checking-for-presence)
    - [Retrieving All Preferences](#retrieving-all-preferences)
    - [Defaults &amp; Missing Values](#defaults--missing-values)
    - [Deleting Preferences](#deleting-preferences)
- [Enum Keys](#enum-keys)
- [Preference Stores](#preference-stores)
    - [Column Driver (JSON Column)](#column-driver-json-column)
    - [Shared Table Driver (Polymorphic)](#shared-table-driver-polymorphic)
    - [Per-Model Table Driver](#per-model-table-driver)
    - [Custom Tables &amp; the Artisan Generator](#custom-tables--the-artisan-generator)
- [Adding Custom Preference Drivers](#adding-custom-preference-drivers)
    - [Implementing a Driver](#implementing-a-driver)
    - [Registering a Driver](#registering-a-driver)
- [Model Cleanup](#model-cleanup)
- [Testing](#testing)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [License](#license)

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

[](#introduction)

Model preferences are small settings that live alongside a model, such as themes, notification options, or feature toggles. This package provides a clean API to read and write preferences with sensible defaults and validation.

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

[](#installation)

First, install the package via Composer:

```
composer require hosmelq/laravel-model-preferences
```

Next, publish the configuration and migration files:

```
php artisan model-preferences:install
```

If you prefer, you may publish the assets manually:

```
php artisan vendor:publish --tag="model-preferences-config"
php artisan vendor:publish --tag="model-preferences-migrations"
```

Finally, run your migrations if you are using the shared or table stores:

```
php artisan migrate
```

Configuration
-------------

[](#configuration)

After publishing the package assets, the configuration file will be located at `config/model-preferences.php`. This configuration file allows you to specify the default store and configure each store.

### Default Store

[](#default-store)

You may specify the default preference store using the `model-preferences.default` configuration value or the `MODEL_PREFERENCES_DRIVER` environment variable. Supported drivers are `column`, `shared`, and `table`.

### Store Configuration

[](#store-configuration)

Each store has its own configuration. For example, you may configure the JSON column name for the `column` driver or the database connection and table name for the shared and table drivers.

### Environment Variables

[](#environment-variables)

The following environment variables are supported:

- `MODEL_PREFERENCES_DRIVER` (default: `shared`)
- `MODEL_PREFERENCES_COLUMN_NAME` (default: `preferences`)
- `MODEL_PREFERENCES_TABLE` (default: `preferences`)
- `MODEL_PREFERENCES_DB_CONNECTION` (default: `DB_CONNECTION`)

Defining Preferences
--------------------

[](#defining-preferences)

### The InteractsWithPreferences Trait

[](#the-interactswithpreferences-trait)

To define preferences on a model, add the `InteractsWithPreferences` trait and implement the `HasPreferences` contract:

```
use HosmelQ\ModelPreferences\Contracts\HasPreferences;
use HosmelQ\ModelPreferences\Models\Concerns\InteractsWithPreferences;
use HosmelQ\ModelPreferences\Support\PreferencesConfig;
use Illuminate\Database\Eloquent\Model;

class User extends Model implements HasPreferences
{
    use InteractsWithPreferences;

    public function preferencesConfig(): PreferencesConfig
    {
        return PreferencesConfig::configure();
    }
}
```

### The preferencesConfig Method

[](#the-preferencesconfig-method)

The `preferencesConfig` method allows you to define defaults, validation rules, and the driver for a given model:

```
use HosmelQ\ModelPreferences\Support\PreferencesConfig as ModelPreferencesConfig;
use Illuminate\Validation\Rule;

public function preferencesConfig(): ModelPreferencesConfig
{
    return ModelPreferencesConfig::configure()
        ->withDefaults([
            'notifications' => true,
            'theme' => 'system',
        ])
        ->withRules([
            'notifications' => ['boolean'],
            'theme' => [Rule::in(['dark', 'light', 'system'])],
        ]);
}
```

### Defaults

[](#defaults)

Defaults may be defined per model using `withDefaults`. These values will be returned when the preference key is not present in the store:

```
use HosmelQ\ModelPreferences\Support\PreferencesConfig;

return PreferencesConfig::configure()
    ->withDefaults([
        'theme' => 'system',
    ]);
```

### Validation Rules

[](#validation-rules)

You may validate preferences using Laravel's validation rules. Rules are evaluated when calling `set`, and a `PreferenceValidationException` will be thrown if validation fails:

```
use App\Models\User;
use HosmelQ\ModelPreferences\Exceptions\PreferenceValidationException;

$user = User::query()->firstOrFail();

try {
    $user->preferences()->set('theme', 'invalid');
} catch (PreferenceValidationException $e) {
    $errors = $e->errors();
}
```

Using Preferences
-----------------

[](#using-preferences)

### Obtaining a Preferences Instance

[](#obtaining-a-preferences-instance)

Call the `preferences` method on your model to obtain a scoped preferences instance:

```
use App\Models\User;

$user = User::query()->firstOrFail();

$preferences = $user->preferences();
```

### Retrieving Preferences

[](#retrieving-preferences)

Use `get` to retrieve a single preference value. You may pass a default value or a closure that will be evaluated lazily. To retrieve multiple preferences at once, use `getMultiple`:

```
use App\Models\User;

$user = User::query()->firstOrFail();

$theme = $user->preferences()->get('theme');
$timezone = $user->preferences()->get('timezone', 'UTC');
$locale = $user->preferences()->get('locale', fn () => app()->getLocale());
$values = $user->preferences()->getMultiple(['theme', 'timezone']);
```

### Storing Preferences

[](#storing-preferences)

Use `set` to store a preference value or `setMultiple` to store multiple values:

```
use App\Models\User;

$user = User::query()->firstOrFail();

$user->preferences()->set('theme', 'dark');
$user->preferences()->setMultiple([
    'theme' => 'dark',
    'locale' => 'en',
]);
```

### Checking for Presence

[](#checking-for-presence)

Use `has` to determine if a preference key exists. You may also use `missing` to check the opposite:

```
use App\Models\User;

$user = User::query()->firstOrFail();

if ($user->preferences()->has('theme')) {
    // ...
}

if ($user->preferences()->missing('timezone')) {
    // ...
}
```

### Retrieving All Preferences

[](#retrieving-all-preferences)

Use `all` to retrieve all stored preferences:

```
use App\Models\User;

$user = User::query()->firstOrFail();

$all = $user->preferences()->all();
```

### Defaults &amp; Missing Values

[](#defaults--missing-values)

Preference lookup follows these rules:

- If the preference exists (even if its value is `null`), `get` returns that value.
- If the preference does not exist and a model default is configured, the default is returned.
- If the preference does not exist and a default is passed to `get`, that default is returned.
- Otherwise, `null` is returned.

### Deleting Preferences

[](#deleting-preferences)

Use `delete` to remove a single preference, `deleteMultiple` for batches, and `clear` to remove all preferences:

```
use App\Models\User;

$user = User::query()->firstOrFail();

$user->preferences()->delete('theme');
$user->preferences()->deleteMultiple(['theme', 'locale']);
$user->preferences()->clear();
```

Enum Keys
---------

[](#enum-keys)

Preference keys may be strings, backed enums, or unit enums. Backed enums use their backed value, while unit enums use their name:

```
use App\Models\User;

enum UserPreference: string
{
    case Theme = 'theme';
}

$user = User::query()->firstOrFail();

$user->preferences()->set(UserPreference::Theme, 'dark');
```

Preference Stores
-----------------

[](#preference-stores)

You may select a store globally via configuration or per model using `withDriver`.

### Column Driver (JSON Column)

[](#column-driver-json-column)

The column driver stores all preferences in a single JSON column on the model's table. You may configure the column name via `withColumn` or the `model-preferences.stores.column.name` setting. When using this driver, the `InteractsWithPreferences` trait automatically adds a JSON cast for the configured column.

Example migration column:

```
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

Schema::table('users', function (Blueprint $table): void {
    $table->json('preferences')->nullable();
});
```

### Shared Table Driver (Polymorphic)

[](#shared-table-driver-polymorphic)

The shared driver stores preferences in a single table using a polymorphic relation. The published migration creates a `preferences` table with `preferable_type`, `preferable_id`, `key`, and `value` columns.

### Per-Model Table Driver

[](#per-model-table-driver)

The table driver stores preferences in a dedicated table per model. When using this driver, you must configure the table name in `preferencesConfig`:

```
use HosmelQ\ModelPreferences\Support\PreferencesConfig;

return PreferencesConfig::configure()
    ->withDriver('table')
    ->withTable('users_preferences');
```

### Custom Tables &amp; the Artisan Generator

[](#custom-tables--the-artisan-generator)

You may generate a preferences table migration using the Artisan command:

```
php artisan model-preferences:table users_preferences
```

This stub creates a table with `model_id`, `key`, and `value` columns and a unique index on `model_id` and `key`.

Adding Custom Preference Drivers
--------------------------------

[](#adding-custom-preference-drivers)

### Implementing a Driver

[](#implementing-a-driver)

To add your own driver, implement the `PreferenceDriver` contract. If you need to distinguish between missing values and `null`, implement `PresenceAwarePreferenceDriver` and return a `PreferenceRead` instance from `getWithPresence`.

```
use HosmelQ\ModelPreferences\Contracts\HasPreferences;
use HosmelQ\ModelPreferences\Contracts\PreferenceDriver;

class CustomDriver implements PreferenceDriver
{
    public function all(HasPreferences $model): array
    {
        return [];
    }

    public function clear(HasPreferences $model): void
    {
        // ...
    }

    public function delete(HasPreferences $model, string $key): void
    {
        // ...
    }

    public function deleteMultiple(HasPreferences $model, array $keys): void
    {
        // ...
    }

    public function get(HasPreferences $model, string $key): mixed
    {
        return null;
    }

    public function getMultiple(HasPreferences $model, array $keys): array
    {
        return [];
    }

    public function has(HasPreferences $model, string $key): bool
    {
        return false;
    }

    public function missing(HasPreferences $model, string $key): bool
    {
        return true;
    }

    public function set(HasPreferences $model, string $key, mixed $value): void
    {
        // ...
    }

    public function setMultiple(HasPreferences $model, array $values): void
    {
        // ...
    }
}
```

### Registering a Driver

[](#registering-a-driver)

Register your driver via the preferences manager, then configure your model to use it:

```
use App\Preferences\CustomDriver;
use HosmelQ\ModelPreferences\PreferencesManager;
use HosmelQ\ModelPreferences\PreferencesStore;

app(PreferencesManager::class)->extend('custom', function () {
    return new PreferencesStore('custom', new CustomDriver());
});
```

```
use HosmelQ\ModelPreferences\Support\PreferencesConfig;

return PreferencesConfig::configure()
    ->withDriver('custom');
```

Model Cleanup
-------------

[](#model-cleanup)

When using the shared or table drivers, the `InteractsWithPreferences` trait automatically removes stored preferences when the model is deleted.

Testing
-------

[](#testing)

```
composer test
```

Changelog
---------

[](#changelog)

See [CHANGELOG.md](CHANGELOG.md) for a list of changes.

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

[](#contributing)

Pull requests are welcome. Please run the test suite before submitting changes.

License
-------

[](#license)

The MIT License (MIT). Please see [License File](LICENSE.md) for more information.

###  Health Score

45

—

FairBetter than 93% of packages

Maintenance85

Actively maintained with recent releases

Popularity24

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity50

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 ~194 days

Total

2

Last Release

106d ago

Major Versions

v0.1.0 → v1.0.02026-02-02

### Community

Maintainers

![](https://www.gravatar.com/avatar/97fd048037c6d5ccfeebf11961838d5db2dca1baca14fefa373230b301389a03?d=identicon)[hosmelq](/maintainers/hosmelq)

---

Top Contributors

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

---

Tags

eloquentlaravellaravel-preferenceslaravel-settingsphppreferencessettingsphplaravelSettingseloquentpreferenceslaravel-settingshosmelqlaravel-preferences

###  Code Quality

TestsPest

Static AnalysisPHPStan, Rector

Code StyleLaravel Pint

Type Coverage Yes

### Embed Badge

![Health badge](/badges/hosmelq-laravel-model-preferences/health.svg)

```
[![Health](https://phpackages.com/badges/hosmelq-laravel-model-preferences/health.svg)](https://phpackages.com/packages/hosmelq-laravel-model-preferences)
```

###  Alternatives

[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[watson/validating

Eloquent model validating trait.

9723.3M47](/packages/watson-validating)[spiritix/lada-cache

A Redis based, automated and scalable database caching layer for Laravel

591444.8k2](/packages/spiritix-lada-cache)[clickbar/laravel-magellan

This package provides functionality for working with the postgis extension in Laravel.

423715.4k1](/packages/clickbar-laravel-magellan)[reedware/laravel-relation-joins

Adds the ability to join on a relationship by name.

2121.2M13](/packages/reedware-laravel-relation-joins)[outerweb/settings

Application wide settings stored in your database

4899.2k5](/packages/outerweb-settings)

PHPackages © 2026

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