overtrue/laravel-options
A simple key-value options manager for Laravel. Store application settings in the database, cache them for fast retrieval, and access values through helpers or the Options facade. Supports defaults, forgetting, and bulk updates.
Architecture fit. overtrue/laravel-options is a narrow, single-purpose persistence package: a settings/options table exposed through a small static API (Option::get()), a pluggable provider contract (provider(?string $name = null)), lifecycle events, and an artisan console command for manipulation. It occupies the "runtime-editable configuration" niche that sits between config/*.php (deploy-time only) and a full feature-flag/settings service. Integration surface is one service provider, one schema, and a handful of static calls — low architectural blast radius. It is a poor fit for high-write or per-request-mutation workloads, and it is not a substitute for env/config; positioning it as an admin-editable settings store is the defensible use case.
Integration feasibility. The gating factors are hard and external to the package: PHP 8.3+ and Laravel 13.x. Any application on Laravel 9–11 or PHP ≤8.2 cannot consume 4.0.0 at all and must stay on 3.x. Conversely, for a team already committed to a Laravel 13 upgrade, this is a low-friction rider — the release explicitly preserves the persistence schema and the provider/event APIs, so the breaking surface is the platform floor, not the package's own contracts.
Technical risk. Moderate-to-low, with caveats:
Option::get('0') and no-argument Option::get() TypeErrors were real, reproduced defects now regression-tested. Fixes are good, but the '0' case touches falsy-string coercion — worth a targeted check of any code path that previously relied on the throw or on loose comparison of stored values.provider(?string $name = null) explicitly nullable removes a PHP 8.4 deprecation without changing accepted inputs. Low risk, but it also means a null that used to surface as a deprecation/error now flows through silently; confirm that is intended at call sites.'0' vs JSON).Key questions.
'0' fix change observable behavior for any caller that caught or worked around the previous TypeError?Stack fit. Fits cleanly into a standard Laravel service-provider model with a published config and migration. No queue, no external service, no runtime daemon. The only hard prerequisites are the PHP and framework floors.
Migration path (3.x → 4.0.0).
UPGRADE.md before touching constraints — it is the authoritative source and this assessment is based on release notes only.^4.0 and run composer update overtrue/laravel-options.Compatibility. The real blocker is rarely this package — it is transitive resolution. Audit for any dependency pinning laravel/framework below 13 or PHP below 8.3 before scheduling the bump. If the application is staying on Laravel 9–11, the correct action is to pin ^3.0 deliberately (not leave it floating) and record the 3.x support horizon as a tracked risk.
Sequencing. Do not upgrade this package independently. Bundle it into the Laravel 13 upgrade as a trailing step, after framework and PHP are green in CI. Update the CI matrix to include PHP 8.3 (lowest) and 8.4/8.5 (highest) to mirror the package's own validation. If Laravel 13 is not on the roadmap, this release warrants no engineering action beyond a constraint pin and a calendar reminder.
Maintenance. Small, low-churn dependency with a narrow public API — minimal ongoing maintenance burden. Positive signals: Composer security-advisory blocking is enabled in the package's own CI, platform checks and dependency audits pass, and dev dependencies are current (Testbench 11, PHPUnit 12.5). Principal maintenance risk is maintainer concentration and the support lifetime of the 3.x branch for teams that cannot move.
Support. Two supported lines in practice (3.x for Laravel 9–11, 4.x for Laravel 13) means two sets of answers to the same questions. Document internally which line each application is on and forbid cross-version copy-paste of snippets.
Scaling. Reads dominate; the options table is small and cache-friendly. Two things matter at scale: (a) a cache layer in front of reads with explicit invalidation on write, and (b) awareness that in a multi-server deployment a write on one node must invalidate caches on all of them. Writes should be rare and administrative. Confirm the package's cache behavior before assuming either.
Failure modes.
register(), a DB blip becomes an application-wide outage. Keep option reads lazy and behind defaults.'0' and no-argument get() defects are the visible tip of a class of bugs. Add application-level tests for stored values that look numeric, boolean, null, or JSON.composer update, blocking the whole Laravel 13 initiative until resolved.provider(null) change — a null that previously errored now passes through to a default provider; verify the fallback is the one you expect.Ramp-up. Low for engineers: the API is a few static calls and one console command. The onboarding burden is conceptual, not syntactic — new team members need to know that (1) these values are DB-backed and cache-fronted, not config(), (2) the deploy procedure includes a cache clear, and (3) mutations go through the console command or the provider, not raw SQL. A short internal README on those three points covers it.
How can I help you explore Laravel packages today?