PHPackages                             osoobe/laravel-settings - 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. [Utility &amp; Helpers](/categories/utility)
4. /
5. osoobe/laravel-settings

ActivePackage[Utility &amp; Helpers](/categories/utility)

osoobe/laravel-settings
=======================

A description for laravel-settings.

2.4.1(3w ago)024MITPHPPHP ^8.1CI passing

Since Feb 12Pushed 3w agoCompare

[ Source](https://github.com/osoobe/laravel-settings)[ Packagist](https://packagist.org/packages/osoobe/laravel-settings)[ RSS](/packages/osoobe-laravel-settings/feed)WikiDiscussions master Synced today

READMEChangelog (7)Dependencies (10)Versions (11)Used By (0)

laravel-settings
================

[](#laravel-settings)

[![Software License](https://camo.githubusercontent.com/55c0218c8f8009f06ad4ddae837ddd05301481fcf0dff8e0ed9dadda8780713e/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d4d49542d627269676874677265656e2e7376673f7374796c653d666c61742d737175617265)](LICENSE.md)![Travis](https://camo.githubusercontent.com/78c48d391d86feab9191d6b2f0314225f9555f54aa4d8be63beccbe4735dbc42/68747470733a2f2f696d672e736869656c64732e696f2f7472617669732f6f736f6f62652f6c61726176656c2d73657474696e67732e7376673f7374796c653d666c61742d737175617265)[![Total Downloads](https://camo.githubusercontent.com/741c008fb7ca2293e35c0849e782a3be24e4a6bdcb3fa3f32142109a3630abe5/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f64742f6f736f6f62652f6c61726176656c2d73657474696e67732e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/osoobe/laravel-settings)

A Laravel package for dynamically storing, overriding, and retrieving Laravel system configs and per-model settings at runtime — without touching `.env` or config files.

Values are persisted to the database, automatically type-cast on read, and can be cached or encrypted. The package ships two independent storage systems:

- **`AppMeta`** — global, application-wide key/value settings.
- **`ModelMeta`** — per-Eloquent-model key/value settings, attached via a polymorphic relation.

Install
-------

[](#install)

```
composer require osoobe/laravel-settings
```

The service provider is auto-discovered. Run the migrations to create the `app_metas` and `model_metas` tables:

```
php artisan migrate
```

---

Use Cases
---------

[](#use-cases)

- **Override Laravel config at runtime** — store a value in `AppMeta` and retrieve it with `AppMeta::config('mail.from.address')`. The DB value takes precedence over `config()`, so you can change settings without a deploy.
- **Encrypted credentials** — store third-party API keys or passwords encrypted in the DB with `AppMeta::setSecret()` and retrieve them decrypted with `AppMeta::secret()`.
- **Per-user or per-model settings** — attach arbitrary key/value pairs to any Eloquent model (e.g. user preferences, per-tenant config) using the `HasMetas` trait.
- **Feature flags** — store boolean flags in `AppMeta` and read them anywhere in the application.
- **Versioned or grouped settings** — subclass `AppMeta` with a custom `CATEGORY` constant to namespace settings for a specific domain (e.g. `PaymentSettings`, `MailSettings`).
- **Audit / change history** — use the `History` trait on any `HasMetas` model to record a diff log of field changes automatically.

---

AppMeta — Global Application Settings
-------------------------------------

[](#appmeta--global-application-settings)

`AppMeta` stores application-wide key/value pairs in the `app_metas` table.

### Dynamic Laravel Config Override

[](#dynamic-laravel-config-override)

`AppMeta::config()` checks the database first and falls back to Laravel's `config()`. This means you can override any config value at runtime without changing files or redeploying.

```
use Osoobe\Laravel\Settings\Models\AppMeta;

// Read: DB value takes precedence over config files
$name = AppMeta::config('app.name', 'My App');

// Write: persists to DB and updates the runtime config() value
AppMeta::setConfig('app.name', 'My New App');

// Later in the same request, config('app.name') also returns 'My New App'
```

### Encrypted Secrets

[](#encrypted-secrets)

Use `secret` / `setSecret` for values that should be stored encrypted (API keys, passwords, tokens). The value is encrypted with Laravel's `encrypt()` before being written and decrypted transparently on read.

```
// Store an API key encrypted
AppMeta::setSecret('services.stripe.secret', 'sk_live_...');

// Retrieve decrypted; falls back to config('services.stripe.secret') if not in DB
$key = AppMeta::secret('services.stripe.secret');
```

### Basic CRUD

[](#basic-crud)

```
// Read a value (returns the typed PHP value, not the raw string)
AppMeta::getMeta('site.maintenance', false);

// Write (upsert)
AppMeta::updateMeta('site.maintenance', true);

// Read or seed if missing
AppMeta::getOrCreateMeta('site.launch_date', '2024-01-01');

// Check existence
AppMeta::keyExists('site.maintenance'); // bool

// Read with permanent cache (auto-creates record if missing)
AppMeta::getMetaOrCached('site.maintenance', false);

// Write and update cache atomically
AppMeta::updateOrCreateWithCache('site.maintenance', false);

// All settings grouped by category
AppMeta::getAppSettingsByCategory();
```

### Category Scoping via Subclassing

[](#category-scoping-via-subclassing)

Subclass `AppMeta` and set a `CATEGORY` constant to namespace a group of settings. All queries on the subclass are automatically scoped to that category.

```
class MailSettings extends AppMeta {
    const CATEGORY = 'mail';

    public static function getKeyPrefix(): string {
        return 'mail_meta_';
    }
}

MailSettings::setConfig('mail.from.address', 'hello@example.com');
MailSettings::config('mail.from.address'); // only searches the 'mail' category
```

---

ModelMeta — Per-Model Settings
------------------------------

[](#modelmeta--per-model-settings)

`ModelMeta` stores key/value pairs scoped to an individual Eloquent model instance in the `model_metas` table. Uniqueness is composite on `(model_id, model_type, meta_key)`.

Add the `HasMetas` trait to any Eloquent model:

```
use Osoobe\Laravel\Settings\Traits\HasMetas;

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

### Usage

[](#usage)

```
$user = User::find(1);

// Read a typed value directly
$theme = $user->getMetaValue('theme'); // e.g. 'dark'

// Read the ModelMeta record
$meta = $user->getMeta('theme');

// Write (upsert)
$user->updateMeta('theme', 'dark');

// All settings grouped by category
$user->getSettingsByCategory();

// Query scope: find users with a specific meta key/value
User::hasMetas('role', 'admin')->get();
User::hasMetas('newsletter')->get(); // key exists, any value
```

---

EnumConfig — Enum-Driven Config Keys
------------------------------------

[](#enumconfig--enum-driven-config-keys)

Apply `EnumConfig` to a PHP backed enum whose `value` is a config/meta key. This gives you a type-safe API for all your application settings.

```
use Osoobe\Laravel\Settings\Traits\EnumConfig;

enum AppSettings: string {
    use EnumConfig;

    case SiteName    = 'app.name';
    case MaintenanceMode = 'app.maintenance';
    case StripeKey   = 'services.stripe.secret';
}

// Read (DB overrides config file)
AppSettings::SiteName->config('Default Name');

// Write (persists to DB + updates runtime config)
AppSettings::SiteName->setConfig('My App');

// Encrypted secret
AppSettings::StripeKey->setSecret('sk_live_...');
AppSettings::StripeKey->secret();
```

---

History — Automatic Change Tracking
-----------------------------------

[](#history--automatic-change-tracking)

Add the `History` trait to any model that already uses `HasMetas`. It hooks into `created` and `updated` Eloquent events and appends a diff to a `history` meta entry. Implement `metaTrack()` to declare which fields to watch.

```
use Osoobe\Laravel\Settings\Traits\HasMetas;
use Osoobe\Laravel\Settings\Traits\History;

class Order extends Model {
    use HasMetas, History;

    public function metaTrack(): array {
        return ['status', 'total'];
    }
}

// Retrieve the full history array
$order->getMetaHistory();
```

Each history entry contains the tracked field values at the time of the event, a `history_status` (`"created"` or `"updated"`), the `updated_at` timestamp, and a Unix `timestamp`.

---

Type Handling
-------------

[](#type-handling)

Values are always stored as strings in the database. The `meta_type` column records the PHP type (`string`, `integer`, `boolean`, `array`, etc.) and is set automatically on every write. Reading a record via the `value` accessor or any helper method returns the correctly typed PHP value — arrays are JSON-encoded on write and decoded on read.

**Never read `meta_value` directly.** Always use the `value` accessor or the provided helper methods.

---

Caching
-------

[](#caching)

`getMetaOrCached()` stores values in `Cache::forever()` and auto-creates the DB record if it doesn't exist. The cache key is `{prefix}{meta_key}` — `app_meta_` for `AppMeta` and `model_meta_` for `ModelMeta`. Override `getKeyPrefix()` on a subclass to avoid collisions.

```
// Reads from cache; writes to cache + DB on first call
AppMeta::getMetaOrCached('site.name', 'My App');

// Write and refresh cache
AppMeta::updateOrCreateWithCache('site.name', 'New Name');
```

---

Examples
--------

[](#examples)

### 1. Maintenance Mode Middleware

[](#1-maintenance-mode-middleware)

Toggle maintenance mode from the database without touching `.env` or redeploying.

```
// app/Http/Middleware/CheckMaintenance.php
use Osoobe\Laravel\Settings\Models\AppMeta;

class CheckMaintenance
{
    public function handle(Request $request, Closure $next)
    {
        if (AppMeta::getMetaOrCached('site.maintenance', false)) {
            abort(503, 'We are currently down for maintenance.');
        }

        return $next($request);
    }
}
```

```
// Turn maintenance on/off from anywhere (e.g. an admin panel)
AppMeta::updateOrCreateWithCache('site.maintenance', true);
AppMeta::updateOrCreateWithCache('site.maintenance', false);
```

---

### 2. Admin Panel: Override Mail Settings at Runtime

[](#2-admin-panel-override-mail-settings-at-runtime)

Allow an admin to change the application's mail config through a form. The new values take effect immediately in the same process — no redeploy needed.

```
// app/Http/Controllers/Admin/MailSettingsController.php
use Osoobe\Laravel\Settings\Models\AppMeta;

class MailSettingsController extends Controller
{
    public function show()
    {
        return view('admin.mail', [
            'from_address' => AppMeta::config('mail.from.address', config('mail.from.address')),
            'from_name'    => AppMeta::config('mail.from.name', config('mail.from.name')),
        ]);
    }

    public function update(Request $request)
    {
        $request->validate([
            'from_address' => 'required|email',
            'from_name'    => 'required|string',
        ]);

        AppMeta::setConfig('mail.from.address', $request->from_address);
        AppMeta::setConfig('mail.from.name', $request->from_name);

        return back()->with('success', 'Mail settings updated.');
    }
}
```

---

### 3. Storing an Encrypted Third-Party API Key

[](#3-storing-an-encrypted-third-party-api-key)

Store sensitive credentials encrypted in the database and retrieve them anywhere.

```
// Store once (e.g. from an admin form)
AppMeta::setSecret('services.stripe.secret', $request->stripe_secret_key);
AppMeta::setSecret('services.sendgrid.key', $request->sendgrid_api_key);

// Retrieve decrypted in a service class
class StripePaymentService
{
    public function client(): \Stripe\StripeClient
    {
        return new \Stripe\StripeClient(AppMeta::secret('services.stripe.secret'));
    }
}
```

---

### 4. Enum-Backed Settings for a Payment Service

[](#4-enum-backed-settings-for-a-payment-service)

Use `EnumConfig` to define all config keys in one place with full IDE autocompletion.

```
// app/Enums/PaymentConfig.php
use Osoobe\Laravel\Settings\Traits\EnumConfig;

enum PaymentConfig: string
{
    use EnumConfig;

    case StripeKey       = 'services.stripe.secret';
    case Currency        = 'payment.currency';
    case MaxRetries      = 'payment.max_retries';
    case WebhookEnabled  = 'payment.webhook_enabled';
}
```

```
// Seed defaults on first boot (e.g. in a seeder or AppServiceProvider)
PaymentConfig::Currency->setConfig('USD');
PaymentConfig::MaxRetries->setConfig(3);
PaymentConfig::WebhookEnabled->setConfig(true);
PaymentConfig::StripeKey->setSecret(env('STRIPE_SECRET'));

// Read anywhere — DB overrides config file
$currency = PaymentConfig::Currency->config('USD');       // 'USD'
$retries  = PaymentConfig::MaxRetries->config(3);         // 3 (int)
$enabled  = PaymentConfig::WebhookEnabled->config(false); // true (bool)
$key      = PaymentConfig::StripeKey->secret();           // decrypted key
```

---

### 5. Per-User Preferences with HasMetas

[](#5-per-user-preferences-with-hasmetas)

Store arbitrary per-user settings without adding columns to the `users` table.

```
// app/Models/User.php
use Osoobe\Laravel\Settings\Traits\HasMetas;

class User extends Authenticatable
{
    use HasMetas;
}
```

```
// app/Http/Controllers/UserPreferencesController.php
class UserPreferencesController extends Controller
{
    public function update(Request $request)
    {
        $user = $request->user();

        $user->updateMeta('theme', $request->input('theme', 'light'));
        $user->updateMeta('locale', $request->input('locale', 'en'));
        $user->updateMeta('notifications_enabled', $request->boolean('notifications_enabled'));

        return back()->with('success', 'Preferences saved.');
    }

    public function show(Request $request)
    {
        $user = $request->user();

        return response()->json([
            'theme'                  => $user->getMetaValue('theme'),
            'locale'                 => $user->getMetaValue('locale'),
            'notifications_enabled'  => $user->getMetaValue('notifications_enabled'),
        ]);
    }
}
```

```
// Query all admin users by a meta value
$admins = User::hasMetas('role', 'admin')->get();

// Query users who have opted into a newsletter (key exists, any value)
$subscribers = User::hasMetas('newsletter')->get();
```

---

### 6. Audit Trail with History

[](#6-audit-trail-with-history)

Track field changes on any model automatically using the `History` trait.

```
// app/Models/Order.php
use Osoobe\Laravel\Settings\Traits\HasMetas;
use Osoobe\Laravel\Settings\Traits\History;

class Order extends Model
{
    use HasMetas, History;

    public function metaTrack(): array
    {
        return ['status', 'total', 'payment_method'];
    }
}
```

```
// Every save automatically appends a diff to the 'history' meta key.
$order = Order::create(['status' => 'pending', 'total' => 99.99]);
// history: [['status' => 'pending', 'total' => 99.99, 'history_status' => 'created', ...]]

$order->update(['status' => 'paid']);
// history: [..., ['status' => 'paid', 'history_status' => 'updated', 'timestamp' => ...]]

// Read the full audit log
$history = $order->getMetaHistory();

foreach ($history as $entry) {
    echo "{$entry['history_status']} at {$entry['updated_at']}: status → {$entry['status']}";
}
```

---

### 7. Grouped Settings via AppMeta Subclass

[](#7-grouped-settings-via-appmeta-subclass)

Subclass `AppMeta` with a `CATEGORY` constant to keep domain-specific settings isolated.

```
// app/Models/Settings/SeoSettings.php
use Osoobe\Laravel\Settings\Models\AppMeta;

class SeoSettings extends AppMeta
{
    const CATEGORY = 'seo';

    public static function getKeyPrefix(): string
    {
        return 'seo_meta_';
    }
}
```

```
// All reads and writes are automatically scoped to category = 'seo'
SeoSettings::setConfig('seo.meta_title', 'My Site — Home');
SeoSettings::setConfig('seo.meta_description', 'Welcome to my site.');
SeoSettings::updateMeta('seo.robots', 'index, follow');

$title       = SeoSettings::config('seo.meta_title');
$description = SeoSettings::getMeta('seo.meta_description');

// Retrieve all SEO settings grouped by category
$grouped = SeoSettings::getAppSettingsByCategory();
```

---

Testing
-------

[](#testing)

```
composer test
# or
vendor/bin/phpunit
```

---

Changelog
---------

[](#changelog)

Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

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

[](#contributing)

Please see [CONTRIBUTING](CONTRIBUTING.md) for details.

Credits
-------

[](#credits)

- [Oshane Bailey](https://github.com/osoobe)
- [All Contributors](https://github.com/osoobe/laravel-settings/contributors)

Security
--------

[](#security)

If you discover any security-related issues, please email  instead of using the issue tracker.

License
-------

[](#license)

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

###  Health Score

47

—

FairBetter than 93% of packages

Maintenance94

Actively maintained with recent releases

Popularity8

Limited adoption so far

Community8

Small or concentrated contributor base

Maturity65

Established project with proven stability

 Bus Factor1

Top contributor holds 72.9% 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 ~263 days

Recently: every ~7 days

Total

7

Last Release

26d ago

Major Versions

1.0.0 → 2.0.02026-05-11

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/1830494?v=4)[Oshane Bailey](/maintainers/b4oshany)[@b4oshany](https://github.com/b4oshany)

---

Top Contributors

[![b4oshany](https://avatars.githubusercontent.com/u/1830494?v=4)](https://github.com/b4oshany "b4oshany (43 commits)")[![claude](https://avatars.githubusercontent.com/u/81847?v=4)](https://github.com/claude "claude (16 commits)")

---

Tags

configsconfigurationenvironment-variableslaravel-frameworklaravel-packagesettingslaravel

### Embed Badge

![Health badge](/badges/osoobe-laravel-settings/health.svg)

```
[![Health](https://phpackages.com/badges/osoobe-laravel-settings/health.svg)](https://phpackages.com/packages/osoobe-laravel-settings)
```

###  Alternatives

[psalm/plugin-laravel

Psalm plugin for Laravel

3355.3M345](/packages/psalm-plugin-laravel)[renatomarinho/laravel-page-speed

Laravel Page Speed

2.5k1.7M11](/packages/renatomarinho-laravel-page-speed)[vinkius-labs/laravel-page-speed

Laravel Page Speed

2.5k12.5k1](/packages/vinkius-labs-laravel-page-speed)[emargareten/inertia-modal

Inertia Modal is a Laravel package that lets you implement backend-driven modal dialogs for Inertia apps.

90142.9k](/packages/emargareten-inertia-modal)[wearepixel/laravel-cart

A cart implementation for Laravel

1374.8k](/packages/wearepixel-laravel-cart)[tomshaw/electricgrid

A feature-rich Livewire package designed for projects that require dynamic, interactive data tables.

119.4k](/packages/tomshaw-electricgrid)

PHPackages © 2026

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