Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Kame Settings Laravel Package

kamekun/kame-settings

Kame Settings is a Laravel package for managing application settings, letting you store, retrieve, and organize configurable values in your database with a simple, developer-friendly API.

View on GitHub
Deep Wiki
Context7

Getting Started

kamekun/kame-settings is a small, single-purpose package: a database-backed key/value store with dot-notation keys, an optional cache layer, and a facade. It was extracted from the KAME CMS (Laravel + Livewire + Tailwind), so it is most comfortable in exactly that kind of admin-panel application.

Install and pin. Because the package is pre-1.0 and has no changelog beyond "Test the new refactor for package.", do not use a caret constraint:

composer require kamekun/kame-settings:0.2.0

Commit the lockfile. Verify the PHP/Laravel constraints in vendor/kamekun/kame-settings/composer.json before installing — the last release is from January 2022 (Laravel 8/9 era), so on Laravel 10+ you should expect to fork or at least adjust constraints.

Publish and migrate. Tag names are not documented, so list them rather than guessing:

php artisan vendor:publish --provider="Kamekun\KameSettings\SettingsServiceProvider"

Then inspect config/kame-settings.php and the published migration, and run:

php artisan migrate

Register the facade if it is not auto-discovered. The package predates some auto-discovery edge cases; if Settings::get() is undefined, add the alias to config/app.php:

'aliases' => [
    'Settings' => Kamekun\KameSettings\Facades\Settings::class,
],

Where to look first, in this order:

  1. vendor/kamekun/kame-settings/src/ — the facade's docblock is the real API documentation.
  2. The published migration — this tells you the table name, whether values are stored as strings/JSON, and whether there is any group/type column.
  3. config/kame-settings.php — cache store, TTL, and table name.

First use case is the canonical one: application-level, runtime-editable values that do not belong in .env — site title, contact email, a support phone number, feature toggles — edited from a Livewire admin screen.

$title = Settings::get('site.title', config('app.name'));
Settings::set('site.title', 'Acme Dashboard');

Implementation Patterns

Never call the facade directly from views or scattered controllers. Wrap it on day one. The package is at 0.2.0 with no changelog, so assume you will eventually replace or fork it; a single wrapping class makes that a one-file change and gives you a place for typed casts and a canonical key list.

namespace App\Support;

final class AppSettings
{
    public const SITE_TITLE   = 'site.title';
    public const SUPPORT_EMAIL = 'site.support_email';
    public const BETA_ENABLED = 'features.beta';

    public static function title(): string
    {
        return (string) \Settings::get(self::SITE_TITLE, config('app.name'));
    }

    public static function betaEnabled(): bool
    {
        return filter_var(
            \Settings::get(self::BETA_ENABLED, false),
            FILTER_VALIDATE_BOOLEAN
        );
    }

    public static function set(string $key, mixed $value): void
    {
        \Settings::set($key, $value);
    }
}

Constants beat string literals: a typo in 'site.titel' returns the default silently and you lose an hour.

Cast at the boundary, not in the database. The store almost certainly holds strings. Keep the raw store dumb and do typed coercion in the wrapper. If you need richer values (arrays, booleans, dates), check whether the migration column is text and serialise JSON yourself with a consistent helper.

Prefer config for boot-time, settings for runtime. Anything Laravel needs before the container is fully up (mail transport, queue connection, filesystem disks) should stay in config/ and .env. Settings are for values that an admin changes while the app is running. Mixing the two is the main architectural mistake with this class of package.

Seed defaults idempotently, so a fresh environment behaves the same as production:

// database/seeders/SettingsSeeder.php
foreach ([
    AppSettings::SITE_TITLE => config('app.name'),
    AppSettings::BETA_ENABLED => '0',
] as $key => $value) {
    if (\Settings::get($key) === null) {
        \Settings::set($key, $value);
    }
}

Run it in your deploy pipeline after migrate. Use "set if missing" semantics, not blind overwrite, or you will clobber production values on every deploy.

Livewire admin form pattern. This is the intended use case:

class SettingsForm extends Component
{
    public string $title = '';
    public string $supportEmail = '';
    public bool $beta = false;

    public function mount(): void
    {
        $this->title        = AppSettings::title();
        $this->supportEmail = AppSettings::supportEmail();
        $this->beta         = AppSettings::betaEnabled();
    }

    public function save(): void
    {
        $data = $this->validate([
            'title'        => ['required', 'string', 'max:120'],
            'supportEmail' => ['required', 'email'],
            'beta'         => ['boolean'],
        ]);

        AppSettings::set(AppSettings::SITE_TITLE, $data['title']);
        AppSettings::set(AppSettings::SUPPORT_EMAIL, $data['supportEmail']);
        AppSettings::set(AppSettings::BETA_ENABLED, $data['beta'] ? '1' : '0');

        $this->dispatch('settings-saved');
    }
}

Hydrate in mount(), validate on save, write each key explicitly. Avoid a generic "loop over request input and set everything" saver — it makes it trivial for a crafted request to overwrite keys you never exposed.

Bulk reads. If you render a page that reads ten settings, verify whether the facade issues one query per get() or loads the table once. If it is per-key, add a memoisation layer in your wrapper (a static array populated on first access) rather than relying on the package's cache.

Testing. Use RefreshDatabase and seed the settings your test needs in setUp(); do not depend on whatever is in the developer's local settings table. If you keep the wrapper class, you can also swap it for a fake in tests and avoid touching the table at all.

Gotchas and Tips

  • The release note is not a changelog. 0.2.0 says only "Test the new refactor for package." Treat every future bump as potentially breaking: read the diff, run your test suite, and pin exactly. This is the single biggest risk with this dependency.
  • The package has been quiet since January 2022. No activity, zero stars. Budget for the possibility that you own it. Mirror the exact version into a private repository so a force-pushed tag cannot break your builds.
  • Reading settings in a service provider's boot() is a classic footgun. During migrate, in queue workers booting on a fresh database, or in CI before the table exists, a settings read will throw. Either guard it:
    if (! Schema::hasTable('settings')) { return; }
    
    or — better — do not read settings at boot at all.
  • Cache invalidation across multiple servers. If config/kame-settings.php points at the file driver, each web node has its own cache and an admin change made on node A will not appear on node B until TTL expiry. Use a shared store (Redis/Memcached) or flush explicitly in the save path.
  • php artisan config:cache interaction. After publishing or editing the package config, run config:clear locally. In production, make sure the config cache is rebuilt as part of deploy, or config changes silently do nothing.
  • Stale published config after an upgrade. Laravel does not error when a config key is renamed — it falls back to a default, quietly. After any version bump, diff your published config/kame-settings.php against the vendor copy.
  • Dot-notation ambiguity. Confirm how the package splits 'a.b': as a nested lookup or as a literal column value. If it is a literal key, you can safely use dots in names; if it explodes on ., a key containing a dot will never round-trip. Test this once with set('a.b', 1) then get('a.b').
  • Type drift on defaults. get('x', false) and get('x', '0') behave differently under loose comparison. Normalise with filter_var(..., FILTER_VALIDATE_BOOLEAN) in your wrapper and be consistent about how you store booleans ('1'/'0') so get and set agree.
  • Do not store secrets here. Values live in a database table and are copied into the cache; API keys and passwords belong in .env or an encrypted column. If you must, implement encryption in your wrapper before writing.
  • Extension points. If the package publishes a contract or binds a repository interface in its service provider, bind your own implementation in a SettingsServiceProvider registered after the package's. If it does not, fork: it is a small package, and a fork you control is cheaper than a vendored dependency you cannot trust.
  • Rollback plan. Because migrations are published into your app, a package downgrade does not roll back schema. Keep the migration additive (new columns nullable) and snapshot the settings table before any version bump so you can restore values if a refactor changes the storage format.
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
mehedimi/laravel-amp-mail
happones/laravel-vue-i18n-generator
jwerd/inertia-table
siberfx/flysystem-wasabi
hollyit/token-replace
ippanelcom/laravel-sdk
adachsoft/changelog-linter
adachsoft/collection
payerurl/telegrambot-crypto-payment-instant-payout
dskripchenko/laravel-hybrid-search
riorizkyrainey/lara-ced
mehedimi/static-vel
zharp/zharp
nonsapiens/bigquery-model-sync
lgu-bayambang-ict-office/lgu-laravel-development-standards
andydefer/laravel-support
se7enxweb/flysystem
lampwick/laravel
jeslage/statamic-emojis
micahdshackelford/rmap-laravel