Skip to content

Reference

phil/feature-flags-bundle

The public API by layer. All classes are under Phil\FeatureFlagsBundle\. State: implemented (tested in tests/Unit or tests/Functional), port (an interface the application implements or may implement), wired (registered by the bundle from configuration).

Domain depends only on phil/ddd-bundle (for InvalidValue and DomainError); Application adds psr/clock; Infrastructure adds Doctrine DBAL and ORM, the HTTP kernel and routing, the console and Twig.

Domain\Flag

TypeRoleState
FlagNameThe name of a flag: lowercase ASCII segments separated by ., _, -, at most 100 bytes.implemented
FlagDefinitionA flag as a provider knows it: active state, rules, experiment, metadata; evaluate(), withActive(), readsAnyOf().implemented
EvaluationThe outcome for one flag and one context: enabled, reason, error code, variant; notFound(), failed().implemented
EvaluationReasonSTATIC, TARGETING_MATCH, SPLIT, DEFAULT, DISABLED, ERROR (OpenFeature vocabulary).implemented
EvaluationErrorCodeFLAG_NOT_FOUND, PARSE_ERROR, GENERAL (OpenFeature vocabulary).implemented
EvaluationContextTenant, project and subject identifiers, each nullable; of(), anonymous(), get().implemented
TargetingAttributetenant, project, subject.implemented
BucketThe stable bucket 0–99: of() for rollouts, forVariant() for experiments (murmur3a).implemented
PercentageA whole percentage 0–100; admits(Bucket).implemented
ExperimentWeighted variants on one attribute; assign().implemented
VariantOne arm and its weight 0–100.implemented
VariantNameThe name of a variant, at most 50 bytes.implemented
FlagMetadataDescription, owner, kind, expiry date; isExpiredAt().implemented
FlagKindrelease, experiment, ops, permission.implemented
FlagProviderA source of definitions: find().port
EnumerableFlagProviderA provider that can list its flags: all().port
DiagnosableFlagProviderAn enumerable provider that also lists the flags it cannot read: unreadable().port
UnreadableFlagA flag a provider holds but cannot read: the name as stored and the reason.implemented
FlagStateSourceA source of active states: isActive().port

Domain\Flag\Rule

TypeRoleState
RuleA targeting rule: matches(), matchReason(), reads().port
MemberOfMatches when an attribute is in an explicit set; reason TARGETING_MATCH.implemented
PercentageRolloutMatches a stable share of an attribute's values; reason SPLIT.implemented

Domain\Toggle

TypeRoleState
ToggleReasonA mandatory reason, Unicode-trimmed, at most 1,000 characters; BLANK is the blank character class.implemented
ToggleRequestAn actor asking to set a flag active or inactive, with a reason.implemented
ToggleRecordThe audit line of an applied toggle.implemented

Domain\Edit

TypeRoleState
EditRequestAn actor asking to create a flag (no revision) or change one (with the revision read).implemented
EditRecordThe audit line of an applied creation or edit, definitions before and after.implemented
RevisedDefinitionA stored definition and its revision (at least 1).implemented

Domain\Exception

TypeRoleState
ToggleRefusedThe authorizer refused a change.implemented
UnknownFlagA toggle or edit named a flag that cannot be changed.implemented
ToggleConflictA toggle lost a race.implemented
EditConflictA stale revision, a lost write, or a name already declared.implemented

All implement Phil\DddBundle\Domain\Exception\DomainError.

Application\Flag

TypeRoleState
FlagEvaluatorEvaluates flags once per request and context over ordered providers, a state store and an exposure recorder; definition(), reset().implemented, wired (kernel.reset)
FlagCatalogThe current configuration: entries(), unreadable(), lookup(), find().implemented, wired
CatalogEntryOne flag with its declared definition, source and stored state; effective().implemented
UnreadableEntryOne flag its declaring provider cannot read: name, reason, source.implemented
AnonymousContextResolverA context without attributes.implemented, wired
EvaluationContextResolverBuilds the context of the current request.port
ExposureRecorderCounts A/B exposures by flag and variant.port

Application\Toggle

TypeRoleState
FlagTogglerThe audited toggle: authorize, read, audit, write (compare-and-set or first insert).implemented, wired with toggle
ToggleAuthorizerDecides toggles, creations and edits.port
ToggleAuditorWrites the audit line of each change.port
WritableFlagStoreA state store a toggle writes to: compareAndSet(), insert().port

Application\Edit

TypeRoleState
FlagEditorThe audited creation and edit, conditional on the revision.implemented, wired with toggle and a definition store
WritableFlagDefinitionsThe definitions the admin writes: findRevised(), create(), replace().port

Application\Admin

TypeRoleState
ActorProviderThe operator of the admin screens.port

Application\Circuit

TypeRoleState
FlagCircuitOverrideThe CircuitOverride of phil/circuit-breaker: forces a circuit open while circuit-open.<key> is on; flagFor(), FORCE_OPEN_FLAG_PREFIX.implemented, wired and tagged phil_circuit_breaker.override

Infrastructure\Configuration

TypeRoleState
ConfiguredFlagProviderThe flags of phil_feature_flags.flags, plus each circuit's force-open flag; enumerable.implemented, wired
FlagDefinitionFormatThe one array shape of a flag, read from configuration, database rows and admin forms, written back to the last two.implemented

Infrastructure\Doctrine

TypeRoleState
DoctrineFlagDefinitionsAdmin-created flags in phil_feature_flags_definition: diagnosable provider (an unreadable row is PARSE_ERROR and listed with its reason) and writable definitions.implemented, tested on SQLite, MySQL and PostgreSQL, wired with doctrine
DoctrineFlagStoreActive states in phil_feature_flags_state.implemented, tested, wired with doctrine
FlagSchemaListenerAdds the tables to the ORM-generated schema.implemented, tested, wired with doctrine
FlagTablesThe table names and configure(Schema).implemented

Infrastructure\Http

TypeRoleState
IsFeatureEnabledController attribute: 404 while the flag is off or outside the variant.implemented
FeatureGateListenerEnforces IsFeatureEnabled on kernel.controller.implemented, wired
FlagAdminControllerThe admin screens: list, show, toggle, create, edit.implemented, wired with admin
SameOriginGuardRefuses cross-site form posts by Sec-Fetch-Site or Origin.implemented

Infrastructure\Routing, Twig, Console

TypeRoleState
Routing\FlagRoutingConditionservice('feature_flags') in route conditions: enabled(), variant(); refuses a flag targeted at subjects or tenants.implemented, wired
Routing\FlagNotRoutableThrown by a route condition that reads a flag targeted at subjects or tenants.implemented
Twig\FeatureFlagsExtensionfeature_enabled() and feature_variant().implemented, wired
Console\ListFlagsCommandphil:feature-flags:list.implemented, wired

Infrastructure\DependencyInjection

TypeRoleState
ForceOpenFlagsPassGives the configuration provider the keys of the circuits of phil/circuit-breaker-bundle, so that each declares its force-open flag.implemented, added by the bundle

Bundle

TypeRoleState
PhilFeatureFlagsBundleConfiguration tree (alias phil_feature_flags), build-time validation, wiring; service id constants.implemented, tested

Resources

PathRole
config/routes/admin.phpThe five admin routes.
templates/admin/layout.html.twigThe default layout (title and content blocks).
templates/admin/list.html.twig, show.html.twig, form.html.twigThe admin screens.