codinglabsau/laravel-feature-flags
A Laravel package for database-backed feature flags. Define flags, enable or disable them globally or for individual users, and check their status in controllers, Blade templates, and middleware through a simple, expressive API.
This release (v1.6.1) is a patch that fixes the FeatureFlag facade alias, which previously pointed at a nonexistent plural class (FeatureFlags). If you are on v1.6.0 or earlier and your FeatureFlag::... calls or @featureflag Blade directives have been throwing "class not found" or alias resolution errors, upgrade first — nothing else changes.
Minimal setup:
composer require codinglabsau/laravel-feature-flagsphp artisan vendor:publish --provider="Codinglabs\FeatureFlags\FeatureFlagsServiceProvider"php artisan migrate to create the feature_flags table.FeatureFlag::isActive('new-checkout') wrapped around a single controller branch — do not retrofit every feature at once.Where to look first:
config/feature-flags.php — table name, caching, and any route/middleware toggles.FeatureFlag model and facade — this is the primary API surface (isActive(), activation/deactivation helpers).src/ for the service provider, which registers the Blade directive and middleware alias.First use case: gate a single new feature (a route, a UI component, or a job dispatch) behind a flag, then verify you can flip it in php artisan tinker without a deploy. That "flip without deploy" loop is the entire value proposition — prove it works before expanding.
Facade-first, with a thin wrapper. Rather than scattering FeatureFlag::isActive('x') through controllers, wrap it in a small domain helper (e.g. Features::newCheckout()) so you have one place to change when the flag is retired. This matters most at cleanup time, when you delete the flag and every call site in one commit.
Blade directives for UI toggles. Use the package's directive for view-level conditionals and the facade in PHP. Keep the same flag name in both — inconsistent naming between Blade and PHP is the most common source of "the flag is on but the button is missing" confusion.
Route middleware for whole surfaces. Register the package's middleware alias and apply it to route groups for beta endpoints. This keeps "is this available at all" separate from "which branch of the code runs," which is easier to reason about and to remove later.
Seed flags in migrations or seeders, not by hand. Every environment — local, CI, staging, prod — should start from the same known flag set with explicit default states. A flag that exists in prod but not in CI means your tests exercise a different code path than production.
Local and CI overrides. Developers should be able to force flags on locally without touching the shared database. Set the flag state in a test setUp() (or the package's fake/override mechanism) so tests are deterministic and do not depend on seeded state. Never let a test depend on the ambient value of a flag.
Artisan commands for operational flips. Toggling via the package's commands or a small custom command is preferable to editing rows by hand — it goes through the model, which keeps any cache invalidation and timestamps consistent. Wire this into your runbook so on-call can disable a bad feature without a deploy.
Retire flags aggressively. Treat every flag as having a planned deletion date. Once a feature is fully rolled out, delete the flag, the branch, and the dead code path in a single PR. Long-lived flags become invisible configuration that no one dares remove.
FeatureFlag alias resolved to a class that does not exist. If you see container or "class not found" errors from the facade, check your installed version first — this is a package bug, not your config.php artisan package:discover (and config:clear / optimize:clear in deployed environments) after composer update, or you may still be running the old broken alias map.isActive('new-thing') before the row exists, the feature silently stays off — usually fine, occasionally a production incident. Decide per flag whether missing means off (rollout) or on (safety-critical path), and make that explicit.isActive() calls produce a combinatorial mess that is untestable. If you need that, you have a configuration problem, not a feature-flag problem.How can I help you explore Laravel packages today?