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

Feature Flags Laravel Package

worksome/feature-flags

A Laravel package for managing feature flags with typed flag classes and model-based scopes. Define flags in code, toggle them per user or entity, and roll out features gradually with a clean, testable API.

View on GitHub
Deep Wiki
Context7

Getting Started

worksome/feature-flags is a small, class-based feature flag package for Laravel. Flags are PHP classes rather than loose config strings, so they are discoverable, testable, and IDE-navigable.

Install and publish

composer require worksome/feature-flags
php artisan vendor:publish --tag="feature-flags-config"

The published config/feature-flags.php is the first file to open — it holds the flag registry/driver settings. If the publish tag differs in your version, run php artisan vendor:publish and pick the package from the list.

First flag in three steps

  1. Generate or hand-write a flag class (there is a make-style generator in the package; otherwise just create the class):
namespace App\FeatureFlags;

use Worksome\FeatureFlags\Contracts\FeatureFlag;

class NewCheckout implements FeatureFlag
{
    public function isActive(): bool
    {
        return $this->user?->isBetaTester() ?? false;
    }
}
  1. Register it in config/feature-flags.php under the flags array, keyed by the string you will reference at call sites (new-checkout).

  2. Resolve it anywhere in the app:

use Worksome\FeatureFlags\Facades\Feature;

if (Feature::active('new-checkout')) {
    // new path
}

Confirm the exact facade alias and contract namespace against vendor/worksome/feature-flags/README.md — they are the two things most likely to shift between majors, and the package is currently on the 5.x line.

First use case: guard one new controller action behind a flag and ship it dark. That validates install, config caching, and your test setup in a single small change.

v5.1.0 note: this release adds Laravel 13 support (laravel/framework: ^13.0). It is a minor, non-breaking bump — no code changes required on Laravel 10–12. If you are moving to Laravel 13, check the package's PHP constraint in composer.json before upgrading, and bump this package in the same PR as the framework so you do not sit on an unsupported combination.

Implementation Patterns

One class per flag, dependencies resolved from the container. Keep flag classes thin and side-effect free. Resolve the current user, request, or tenant from the container rather than constructor-injecting a Request (see Gotchas for Octane).

Compose flags from other flags. For related rollouts, a parent flag calling Feature::active('child-flag') keeps the decision tree in one place instead of duplicating audience logic.

Route middleware for gated areas. Rather than sprinkling if statements through controllers, wrap a group of routes in a small middleware that aborts with 404 when the flag is off. This keeps the disabled surface indistinguishable from a non-existent route.

Blade for UI toggles. Use the package's Blade directive (or a plain @if (Feature::active(...))) around nav entries and buttons. Prefer wrapping the entry point rather than the whole view so the old and new paths stay independently testable.

Tests: pin the flags, do not inherit them. Set flag state explicitly in each test (or in a base TestCase setUp) so a developer's local config cannot change CI outcomes. Test both branches of every flag you touch — the "off" branch is the one that rots silently.

// arrange the flag to a known state before hitting the endpoint
Feature::fake(['new-checkout' => true]);

Staged rollout pattern. Start with an allow-list (staff, then beta users), then percentage by a stable hash of user ID, then everyone, then delete the flag and the dead branch in the same PR that flips it to 100%. Treat "delete the flag" as part of the rollout task, not a follow-up ticket.

Config-driven vs. database-driven. The config driver is fine for deploy-time decisions and is the fastest to reason about. If product needs to flip flags without a deploy, use the database-backed driver if your version ships one — and budget for the cache invalidation work that comes with it.

CI and local parity. Keep flag definitions in version control, not in .env. If a flag needs per-environment values, put the audience in env and the decision logic in the class.

Gotchas and Tips

  • config:cache bites. If flag definitions live in config/feature-flags.php, any closure or non-serialisable value there will break php artisan config:cache in production while working fine locally. Run php artisan config:cache once before deploying a new flag.
  • Unknown flags fail quietly. Referencing a flag key that is not registered typically resolves to false (or throws, depending on config) — a typo looks exactly like a disabled feature. Add a test that asserts every registered key resolves, and consider a boot-time check in non-production.
  • Octane / queue workers hold stale state. Do not cache the result of a flag check in a singleton or constructor on a long-lived worker. Resolve per request/job, or explicitly flush the package cache between requests.
  • Cache TTL vs. "instant" toggles. With a cached driver, flipping a flag is not instantaneous. Know the TTL and the invalidation command, and document it for whoever is on support during a rollout.
  • View caching. Blade-compiled views do not re-evaluate at render time in the way you might expect when paired with cached flag state — if a UI toggle "doesn't take", clear both the flag cache and the view cache before debugging logic.
  • Do not inject Request into flag constructors. Inject Illuminate\Contracts\Container\Container or resolve the user/request lazily inside isActive(); otherwise you capture the first request in a worker and leak audience between users.
  • Extension point: the flag contract is the seam. Custom drivers or audience resolvers should be bound in a service provider and kept out of the flag classes themselves, so flag classes stay trivially unit-testable without a Laravel app.
  • Upgrade hygiene (v5.1.0): minor bump, no deprecations or breaking changes announced. The only action item is the Laravel 13 compatibility matrix — verify PHP and framework constraints across your other packages before bumping, and check that any custom driver you wrote still satisfies the contract if you have pinned to an older 5.x.
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.
pharaonic/laravel-notification-dependencies
beautinow/translug
dev-brainiac/bot-cloaked
octoberrain/html
octoberrain/extension
octoberrain/exception
octoberrain/contracts
frankyso/ipaymu
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
adachsoft/api-version-bundle
cgv/localized-resource
noith/settings
kda/laravel-package
kda/filament-dynamic-navigation
bypersoft/signbox
pairus/product-data
fayne/laravel-filament-cms-core