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 Manager Bundle Laravel Package

alex-bykovski/feature-manager-bundle

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require alex-bykovski/feature-manager-bundle
    

    Add to config/bundles.php:

    AlexBykovski\FeatureManagerBundle\FeatureManagerBundle::class => ['all' => true],
    
  2. Publish Configuration

    php artisan vendor:publish --provider="AlexBykovski\FeatureManagerBundle\FeatureManagerBundle" --tag="config"
    

    This creates config/feature_manager.php. Defaults:

    return [
        'features' => [
            'feature_name' => [
                'active' => true,
                'default' => true,
                'description' => 'Optional feature description',
            ],
        ],
    ];
    
  3. First Use Case: Toggle a Feature In a controller or service:

    use AlexBykovski\FeatureManagerBundle\FeatureManager;
    
    public function __construct(FeatureManager $featureManager) {
        $this->featureManager = $featureManager;
    }
    
    public function someAction() {
        if ($this->featureManager->isActive('feature_name')) {
            // Feature logic
        }
    }
    

Implementation Patterns

Workflows

  1. Feature Flag Management

    • Runtime Toggles: Use feature_manager:toggle Artisan command to enable/disable features without redeploying:
      php artisan feature_manager:toggle feature_name --active=true
      
    • Environment-Specific Flags: Override config/feature_manager.php per environment (e.g., config/feature_manager.local.php).
  2. Dependency Injection

    • Service Providers: Bind custom logic to feature checks:
      $this->app->extend('feature_manager', function ($manager) {
          $manager->addCustomRule('premium_feature', function () {
              return auth()->user()->isPremium();
          });
          return $manager;
      });
      
  3. Database-Backed Features (Advanced)

    • Extend the bundle to store feature states in a features table:
      // Example migration
      Schema::create('features', function (Blueprint $table) {
          $table->string('name')->unique();
          $table->boolean('active')->default(false);
          $table->timestamps();
      });
      
    • Override the FeatureManager service to query the database:
      $this->app->bind('feature_manager', function () {
          return new DatabaseFeatureManager(config('feature_manager.features'));
      });
      
  4. Grouped Features

    • Use nested arrays for hierarchical features:
      'features' => [
          'module_a' => [
              'active' => true,
              'sub_features' => [
                  'sub_feature_1' => ['active' => false],
              ],
          ],
      ],
      
    • Check with:
      $featureManager->isActive('module_a.sub_features.sub_feature_1');
      
  5. Event-Based Activation

    • Trigger feature toggles via events (e.g., user subscription):
      event(new UserSubscribed($user));
      // In listener:
      $featureManager->toggle('premium_feature', true);
      

Gotchas and Tips

Pitfalls

  1. Configuration Overrides

    • Issue: Local overrides (feature_manager.local.php) may not load automatically.
    • Fix: Ensure config/feature_manager.php includes:
      $features = array_merge(
          require __DIR__.'/feature_manager.php',
          config('feature_manager.*.php', [])
      );
      
  2. Caching

    • Issue: Feature flags may not update in real-time if cached (e.g., by OPcache or Laravel cache).
    • Fix: Clear cache after toggling:
      php artisan cache:clear
      php artisan config:clear
      
  3. Case Sensitivity

    • Issue: Feature names are case-sensitive by default.
    • Fix: Normalize names in FeatureManager:
      $featureName = strtolower($featureName);
      
  4. Missing Defaults

    • Issue: Undefined features return false instead of null.
    • Fix: Explicitly check for existence:
      if ($featureManager->has('feature_name') && $featureManager->isActive('feature_name')) {
          // Safe to proceed
      }
      

Debugging

  • Log Feature Checks: Add a debug method to FeatureManager:

    public function debug($featureName) {
        \Log::debug('Feature check for ' . $featureName, [
            'active' => $this->isActive($featureName),
            'config' => $this->getConfig($featureName),
        ]);
    }
    
  • Artisan Command for Dump: Create a custom command to list all features:

    php artisan feature_manager:list
    

    Implementation:

    public function handle() {
        foreach (config('feature_manager.features') as $name => $config) {
            $this->info(sprintf(
                "%-30s | %5s | %s",
                $name,
                $config['active'] ? '✅' : '❌',
                $config['description'] ?? ''
            ));
        }
    }
    

Extension Points

  1. Custom Storage

    • Override FeatureManager to use Redis, DynamoDB, etc.:
      class RedisFeatureManager extends FeatureManager {
          public function isActive($featureName) {
              return Redis::get($this->getRedisKey($featureName)) === 'true';
          }
      }
      
  2. A/B Testing

    • Extend to support percentage-based activation:
      $featureManager->isActiveForUser('experimental_feature', auth()->id());
      
    • Logic in FeatureManager:
      public function isActiveForUser($featureName, $userId) {
          $config = $this->getConfig($featureName);
          if (!$config['active']) return false;
      
          if (isset($config['percentage']) && $config['percentage'] < 100) {
              return mt_rand(1, 100) <= $config['percentage'];
          }
          return true;
      }
      
  3. Feature Analytics

    • Track usage via middleware:
      public function handle($request, Closure $next) {
          if ($featureManager->isActive('analytics_enabled')) {
              Analytics::track('feature_used', ['name' => 'some_feature']);
          }
          return $next($request);
      }
      
  4. Validation Rules

    • Integrate with Laravel Validation:
      use Illuminate\Validation\Rule;
      
      $rules = [
          'user_input' => [
              Rule::requiredIfFeatureActive('feature_name'),
          ],
      ];
      
    • Extend FeatureManager with a static method:
      public static function requiredIfFeatureActive($featureName) {
          return function ($attribute, $value, $fail) {
              if (!self::isActive($featureName) && empty($value)) {
                  $fail('The ' . $attribute . ' field is required when ' . $featureName . ' is active.');
              }
          };
      }
      
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.
elnasnato/laraliveui
labrodev/rest-sdk
sampaui/sampaui
babelqueue/php-sdk
facebook/capi-param-builder-php
babelqueue/symfony
hamzi/corewatch
minionfactory/raw-hydrator
hexters/coinpayment
rjcodes/rjcms
act-training/laravel-permissions-manager
alimarchal/laravel-chart-of-accounts
babenkoivan/elastic-scout-driver
mkwebdesign/filament-watchdog-v5
renatomarinho/laravel-page-speed
zedmagdy/filament-business-hours
renatovdemoura/blade-elements-ui
devgeek/beacon-admin
benjamin-rqt/data-watcher-bundle
atriumphp/atrium