Model or dataset
glorand/laravel-model-settings avatar
glorand/laravel-model-settings

laravel-model-settings: per model settings behind one trait and four drivers

Model Settings for your Laravel app

927 stars60 forksPHPMIT

At a glance

What is it?
laravel-model-settings attaches a HasSettings trait to an Eloquent model and stores that model's settings in a JSON column, a dedicated table, Redis or the cache, with the driver chosen per model or per application. It fits applications with per record preferences, and it is a poor fit when settings need their own validation rules and lifecycle.
Who is it for?
Adopt laravel-model-settings when your Eloquent models need their own per record settings, when you want the same trait to work whether the data lives in a JSON column, a dedicated table or Redis, and when you want to move a model between backends by changing one property.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 66 days ago.
What is it written in?
Mainly PHP, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 7, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • glorand/laravel-model-settings927 ★ · +2
Star history
Repository2026-10-222026-11-07
glorand/laravel-model-settings925927

2 Stars in the last 16 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

One trait for settings that belong to a record rather than a config file

laravel-model-settings gives an Eloquent model a place to keep settings that belong to that record. The package description is short, Model Settings for your Laravel app, and the topics listed are eloquent-models, laravel, laravel-settings, settings and trait. The last of those is the design decision: the whole package is a trait you add to a model.

The gap it fills is a familiar one. Application wide configuration belongs in a config file or in an environment file, but the preferences of one user or one record do not fit there, and shoving them into a column you define by hand means writing the same accessor, mutator and cast code in every model. This package removes that repetition.

The requirements are stated in one line: PHP 8.2 or later and Laravel 12 or later, with the code following the FIG standards PSR-1, PSR-2, PSR-4 and PSR-12. It is an MIT licensed package, and the latest release is V9.1.0 from 2026-09-02, with V9.0.2 and V9.0.1 before it in July 2026.

The documented API surface covers more than reading a value. The table of contents lists checks for whether settings exist or are empty, retrieval of all settings for a model, adding and updating, checking for a specific setting, removing one, persistence behaviour, a way to rename the settings() method, and a validation system for settings data.

The driver picks the backend, and the model property overrides the config

This is where version 9 differs from what many older tutorials show. Storage is selected by a driver rather than by the trait you use, and the default is the field driver, which stores settings as a JSON column on the model's own table.

A driver can be set application wide with the MODEL_SETTINGS_DRIVER environment variable or the driver config key, and per model with the $settingsDriver property, and the documentation is explicit that the model property always wins. So a single application can keep most models on the field driver and put one heavy model on the table driver without any global reconfiguration.

php
class User extends Model
{
    use HasSettings;

    protected $settingsDriver = 'table'; // 'field' (default) | 'table' | 'redis' | 'cache'
}

That single line per model is the entire selection mechanism. The four values in the comment are the whole menu: field, table, redis and cache. Anyone upgrading from an earlier major version should note that this is a different design, and the repository ships a dedicated migration guide for the change.

Installing the package and attaching the trait to a model

Installation is a single Composer command.

shell
$ composer require glorand/laravel-model-settings

The constraint the documentation asks you to write by hand in composer.json is the same package at the major version.

json
{
    "require": {
        "glorand/laravel-model-settings": "^9.0"
    }
}

Then a model opts in with the trait, and nothing else.

php
use Glorand\Model\Settings\Traits\HasSettings;

class User extends Model
{
    use HasSettings;
}

The trait is namespaced under Glorand\Model\Settings\Traits, which is a hint about the older layout of the package, where storage specific traits existed for each backend. Version 9 replaces those three storage specific traits with the single HasSettings trait and the configuration driven driver system, and the documentation points to MIGRATION_GUIDE_8_to_9.md for the full checklist.

Two artisan commands create the storage, and the table name must be set first

Each storage backend that needs a database change has an artisan command that writes the migration for you.

bash
php artisan model-settings:model-settings-field
bash
php artisan model-settings:model-settings-table

The field command creates a JSON field on the mentioned table, using the default name settings taken from the config, and a model can override that name with a public property.

php
public $settingsFieldName = 'user_settings';

The table command copies the migration class into the project so the settings table can be created, and the table name defaults to model_settings. The documentation makes one ordering requirement explicit: if you want a different table name you have to change the config or the env value MODEL_SETTINGS_TABLE_NAME before you run the command, because the generated migration hard codes the name it was created with.

That is a small detail and an easy trap on a project where the table name is a matter of house style, since running the command first and renaming afterwards means editing the migration by hand.

Redis and cache drivers, and why cached settings never expire by default

The two external drivers are configured through the environment, and both take a connection or store name and a key prefix.

bash
MODEL_SETTINGS_REDIS_CONNECTION=
MODEL_SETTINGS_REDIS_PREFIX=r-k-
MODEL_SETTINGS_CACHE_STORE=
MODEL_SETTINGS_CACHE_TTL=
MODEL_SETTINGS_CACHE_PREFIX=c-k-

For Redis, the connection is a named connection and an empty value means the default one. The prefix exists so that settings keys do not collide with other keys in the same Redis instance.

The cache driver is the more interesting one, and it works through Laravel's Cache facade, which means any store configured in config/cache.php can back the settings, including Memcached, DynamoDB, database and file stores. MODEL_SETTINGS_CACHE_STORE picks a named store and an empty value uses the application default.

The behaviour to understand before choosing it is that settings are stored forever by default, because for this driver the cache is the only copy of the data. MODEL_SETTINGS_CACHE_TTL sets an expiry in minutes if you want one. That design is defensible for a settings store, and it is also the reason to pick this driver only where a cache miss can be regenerated from somewhere else, which for per model settings usually it cannot.

Version 9 changed the trait model, and the upgrade is a code change, not a config change

The upgrade path deserves its own attention, because it is not backwards compatible in shape. Version 9 replaces the three storage specific traits with a single HasSettings trait and the configuration driven driver system, and the repository keeps a migration guide file, MIGRATION_GUIDE_8_to_9.md, with the full checklist.

For an application on version 8, the work is mechanical but touches every model that carried a settings trait, plus any place where the storage location was implicit in the trait choice rather than in configuration. Models that used the field driver can usually keep their data, since the field driver keeps the settings in a JSON column on the model table, but the table driver, the Redis driver and the cache driver all move to explicit configuration, and per model overrides are now properties on the model.

The release cadence around the change is worth noting. V9.0.1 and V9.0.2 landed within days of each other in July 2026, and V9.1.0 followed on 2026-09-02, which is also the date of the last push. A 9.0 release that needed two patch releases in the first week is a normal sign of a large refactor settling, and the git history and the changelog file in the repository are where the specifics live.

Where a hand rolled settings column is the better choice

The alternative to this package is not another package, it is the approach most teams reach for first: add a settings or preferences column to the table yourself and write the accessors for that model. If you have one model with one preferences blob, that is less code than adding a dependency, and you get to decide the column type, the casts and the validation.

The package earns its place when the repetition grows. Four models with preferences means four sets of accessors, four definitions of what a default is, and four places to fix a bug in how a preference is cast. With the package, the trait is written once, the driver is chosen per model, and the defaults live in configuration.

The other alternative is to keep the settings outside the database entirely, in the application configuration or in an external settings service. The difference is scope: a config file or a settings service holds one value per key for the whole application, while this package holds a value per model record. If your requirement is actually a per tenant or per environment value, this package is more machinery than the job needs, and no driver configuration will change that.

Editorial conclusion

Adopt laravel-model-settings when your Eloquent models need their own per record settings, when you want the same trait to work whether the data lives in a JSON column, a dedicated table or Redis, and when you want to move a model between backends by changing one property. Do not adopt it if your settings need schema level validation and audit, since the storage is a generic blob per model, and read the section on the cache driver before choosing it, because cached settings are stored forever by default and the cache is the only copy of the data. Before the first run, set MODEL_SETTINGS_DRIVER and MODEL_SETTINGS_FIELD_NAME in the .env file, and if you intend to use the table driver, change MODEL_SETTINGS_TABLE_NAME before you run the artisan command that creates the migration.

Frequently asked questions

How do I install laravel-model-settings?

Run composer require glorand/laravel-model-settings, or add glorand/laravel-model-settings with the ^9.0 constraint to the require block of composer.json. The package needs PHP 8.2 or later and Laravel 12 or later.

What are the storage drivers and how do I choose one?

There are four: field stores settings in a JSON column on the model's own table, table stores them in a separate table with one row per model, redis stores them in Redis, and cache stores them through Laravel's Cache facade. The default is set with MODEL_SETTINGS_DRIVER, and a model overrides it with the $settingsDriver property, which always wins.

How do I create the database storage for laravel-model-settings?

Run php artisan model-settings:model-settings-field to add a JSON field to a model table, or php artisan model-settings:model-settings-table to copy the migration that creates the separate settings table. If you want a different settings table name, change MODEL_SETTINGS_TABLE_NAME before running the command.

Do settings expire when I use the cache driver?

No, they are stored forever by default, because the cache is the only copy of the data for that driver. MODEL_SETTINGS_CACHE_TTL sets an expiry in minutes if you want one, and MODEL_SETTINGS_CACHE_STORE selects a named cache store.

What changed in version 9 of laravel-model-settings?

Version 9 replaces the three storage specific traits with a single HasSettings trait and a configuration driven driver system, so the storage backend is chosen by configuration or by the $settingsDriver property instead of by the trait. The repository includes a migration guide file for the change.

Official sources

  1. glorand/laravel-model-settings on GitHub
  2. Issues
  3. License: MIT
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/glorand-laravel-model-settings.svg)](https://hysenlabs.com/projects/glorand-laravel-model-settings)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/glorand-laravel-model-settings.svg)](https://hysenlabs.com/projects/glorand-laravel-model-settings)

Was this useful?