Weave Code
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 Flag Bundle Laravel Package

check24/feature-flag-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation:

    composer require check24/feature-flag-bundle
    

    Enable the bundle in config/bundles.php:

    return [
        // ...
        Shopping\FeatureFlagBundle\FeatureFlagBundle::class => ['all' => true],
    ];
    
  2. Define Flags in .env:

    FEATURE_FLAGS=foobar=true,another_feature=false
    

    Flags are space-separated KEY=VALUE pairs (case-sensitive).

  3. First Use Case: Check a flag in a controller:

    use Shopping\FeatureFlagBundle\Service\FeatureFlagInterface;
    
    class TestController {
        public function __construct(private FeatureFlagInterface $featureFlag) {}
    
        public function index() {
            if ($this->featureFlag->isActive('foobar')) {
                return new Response('Feature enabled!');
            }
            return new Response('Default behavior.');
        }
    }
    

Key Files to Review

  • config/packages/shopping_feature_flag.yaml (default config)
  • src/Shopping/FeatureFlagBundle/Resources/config/services.yaml (service definitions)

Implementation Patterns

Core Workflows

1. Controller-Level Access Control

Use @IsActive annotation to gate routes:

/**
 * @Route("/experimental")
 * @IsActive("experimental_feature")
 */
public function experimentalRoute() { ... }
  • Pros: Clean, declarative, integrates with Symfony’s security layer.
  • Cons: Requires annotation parsing (ensure doctrine/annotations is installed).

2. Service Injection

Inject FeatureFlagInterface into services for logic branching:

class AnalyticsService {
    public function __construct(private FeatureFlagInterface $flags) {}

    public function trackEvent() {
        if ($this->flags->isActive('analytics_v2')) {
            $this->trackWithV2();
        } else {
            $this->trackWithV1();
        }
    }
}
  • Pattern: Use for conditional feature logic (e.g., A/B tests, gradual rollouts).

3. Twig Integration

Render UI conditionally:

{% if is_active('new_ui') %}
    <button class="btn btn-primary">New Design</button>
{% else %}
    <button class="btn btn-default">Legacy</button>
{% endif %}
  • Tip: Cache Twig templates aggressively if flags change rarely.

4. Custom Providers

Extend functionality (e.g., database-backed flags):

# config/packages/shopping_feature_flag.yaml
shopping_feature_flag:
    providers:
        - { id: 'env', class: 'Shopping\FeatureFlagBundle\Provider\EnvProvider' }
        - { id: 'db', class: 'App\Provider\DatabaseFlagProvider' } # Custom
  • Example Provider:
    class DatabaseFlagProvider implements ProviderInterface {
        public function isActive(string $flag): bool {
            return DB::table('feature_flags')->where('name', $flag)->value('enabled') ?? false;
        }
    }
    

Integration Tips

  • Environment Separation: Use .env for dev/staging/prod parity.
  • Cookie-Based Flags: Enable via config:
    shopping_feature_flag:
        providers:
            - { id: 'cookie', class: 'Shopping\FeatureFlagBundle\Provider\CookieProvider' }
    
    Flags persist per user session (useful for A/B tests).
  • User-Agent Targeting: Useful for browser-specific features:
    providers:
        - { id: 'user_agent', class: 'Shopping\FeatureFlagBundle\Provider\UserAgentProvider' }
    

Gotchas and Tips

Pitfalls

  1. Annotation Parsing:

    • @IsActive requires doctrine/annotations and Symfony’s annotation reader.
    • Fix: Ensure doctrine/annotations is installed and annotations are loaded in services.yaml:
      parameters:
          annotation_reader.class: doctrine/annotations-php80:AnnotationReader
      
  2. Case Sensitivity:

    • Flags in .env are case-sensitive (FEATURE=flagFEATURE=Flag).
    • Tip: Standardize naming (e.g., FEATURE_NEW_CHECKOUT=true).
  3. Provider Order:

    • Providers are evaluated in registration order (first match wins).
    • Debugging: Use bin/console debug:container Shopping\FeatureFlagBundle\Service\FeatureFlag to inspect provider chain.
  4. Caching:

    • The bundle caches flag evaluations by default (configurable via cache_enabled).
    • Issue: Stale flags if .env changes without cache invalidation.
    • Workaround: Clear cache after .env updates:
      php bin/console cache:clear
      
  5. Cookie Provider Quirks:

    • Cookie flags are session-scoped (not persistent across sessions).
    • Tip: Use same-site cookies for cross-subdomain consistency.

Debugging

  • Log Provider Results: Override FeatureFlagInterface to log evaluations:

    class DebugFeatureFlag implements FeatureFlagInterface {
        public function isActive(string $flag): bool {
            $result = $this->delegate->isActive($flag);
            \Log::debug("Flag {$flag} evaluated to {$result}");
            return $result;
        }
    }
    
  • Check Provider Chain: Dump the active providers:

    $providers = $container->get('shopping_feature_flag.provider.chain');
    dump($providers->getProviders());
    

Extension Points

  1. Custom Providers: Implement ProviderInterface:

    class DatabaseProvider implements ProviderInterface {
        public function isActive(string $flag): bool {
            // Custom logic (e.g., Redis, API call)
        }
    }
    

    Register in config/packages/shopping_feature_flag.yaml.

  2. Override Default Behavior: Extend FeatureFlag service:

    services:
        Shopping\FeatureFlagBundle\Service\FeatureFlag:
            class: App\Service\CustomFeatureFlag
            arguments:
                $providers: !tagged 'shopping_feature_flag.provider'
    
  3. Event Listeners: Listen for flag changes (if using dynamic providers):

    class FlagChangeListener {
        public function onKernelRequest(GetResponseEvent $event) {
            if ($event->isMasterRequest()) {
                $this->featureFlag->reload(); // Force refresh
            }
        }
    }
    

Performance

  • Avoid Overhead: Disable caching for dynamic providers (e.g., database):
    shopping_feature_flag:
        cache_enabled: false
    
  • Bulk Checks: For multiple flags, use isAnyActive() or isAllActive() methods if available (check bundle version).

Configuration Quirks

  • Default Values: Flags not found in any provider return false (configurable via default_value in config).
  • Environment Variables: Prefix flags with FEATURE_FLAGS_ for namespace separation:
    FEATURE_FLAGS_NEW=checkout=true,ui_v2=false
    
    Configure in shopping_feature_flag.env_prefix.
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.
besmartand-pro/php-quality-config
sentix/ai-chatbot
terminal42/code-quality-tools
codifyo/ts-generator-bundle
testo/fiber
mintobit/jobqueue
a4sex/maintenance-bundle
a4sex/entity-date-update
a4sex/client-identifier
a4sex/base-utilites
a4sex/key-value-storage
a4sex/micro-status
chilldev/dependency-injection-extra
datinglibre/datinglibre-app-api
biberltd/corebundle
bricre/symfony-bundle-test
biberltd/logbundle
dominium/http-adapter-bundle
dominium/google-analytics
a4sex/auto-clean-entity