serendipity_hq/features-bundle
Serendipity HQ Features Bundle adds a flexible feature-flag system to PHP applications, letting you enable or disable functionality per environment, user, or context. Define features in configuration, check them anywhere, and ship changes safely without redeploying code.
composer require serendipity_hq/features-bundle. This is a Symfony bundle, not a Laravel package — if you're coming from Laravel, expect Symfony conventions (service container, Doctrine entities, bundles.php registration).config/bundles.php (or AppKernel on older Symfony) and make sure doctrine/orm is installed and configured — the bundle ships Doctrine entities for features, plans, feature–plan links, and subscriptions.User (or Customer) class must implement the bundle's CustomerInterface; the bundle uses this to resolve which subscription/plan applies.bin/console doctrine:schema:update --dump-sql first to inspect what tables the bundle adds, then apply via migrations. Check the created tables (feature, plan, feature_plan, subscription, and any usage/counter tables) before writing app code.FeaturesManager service (the primary API), the entity classes, and the README's configuration example. Search the service container for serendipity_hq.features_manager to confirm the ID.Feature with a stable code (e.g. export_csv), attach it to a Plan, create a Subscription for a customer on that plan, then call the manager's customer-has-feature check in a controller before allowing the action.if (!$featuresManager->customerHasFeature($user, 'export_csv')) {
throw $this->createAccessDeniedException('Upgrade your plan.');
}
code string as a stable API identifier used throughout your code (controllers, voters, templates). Define features and plans via fixtures or a seeder command rather than hand-editing rows, so environments stay reproducible.customerHasFeature() calls, create a FeatureVoter that maps attribute => feature code and call denyAccessUnlessGranted('FEATURE_export_csv', $user). This keeps authorization idiomatic and testable with Symfony's security test helpers.{% if can_use('export_csv') %} via a small Twig extension that delegates to the manager, so templates stay clean and you can hide upgrade prompts consistently.Subscription on signup/checkout, update its plan on upgrade/downgrade, and mark it inactive on cancellation. Drive expiry with a scheduled console command (cron) rather than computing everything on read, and make isActive() date-range checks timezone-aware.free and pro plan in fixtures and attach features there.CustomerInterface implementation is mandatory. A common first-run failure is forgetting to configure the customer class or not implementing the interface — the manager will throw when resolving subscriptions. Verify the config key and the class FQCN carefully.vendor/. Don't edit them; extend or override via config where supported, and always regenerate migrations after upgrading the bundle.composer.json, review the changelog between upgrades, and consider forking if you hit a bug. Keep a thin adapter service around FeaturesManager so you can swap implementations later.bin/console debug:container serendipity_hq.features_manager; and log every customerHasFeature/consume decision during rollout to catch mapping mistakes.Subscription, and service overrides via services.yaml are the safest ways to add behavior without patching vendor code. Use a compiler pass or alias to decorate the manager if you need cross-cutting concerns (logging, caching, metrics).How can I help you explore Laravel packages today?