From 9a13e025513531561efaf523c22ddcbebb1a2981 Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 28 May 2026 18:25:12 -0400 Subject: [PATCH 1/3] Add PHP feature flag docs --- config/_default/menus/main.en.yaml | 9 +- content/en/feature_flags/server/php.md | 340 ++++++++++++++++++ .../feature_flags/feature_flags_server.html | 7 + 3 files changed, 354 insertions(+), 2 deletions(-) create mode 100644 content/en/feature_flags/server/php.md diff --git a/config/_default/menus/main.en.yaml b/config/_default/menus/main.en.yaml index 42b1534f03d..2e6d7d26788 100644 --- a/config/_default/menus/main.en.yaml +++ b/config/_default/menus/main.en.yaml @@ -6208,16 +6208,21 @@ menu: parent: feature_flags_server identifier: feature_flags_server_nodejs weight: 204 + - name: PHP + url: feature_flags/server/php + parent: feature_flags_server + identifier: feature_flags_server_php + weight: 205 - name: Python url: feature_flags/server/python parent: feature_flags_server identifier: feature_flags_server_python - weight: 205 + weight: 206 - name: Ruby url: feature_flags/server/ruby parent: feature_flags_server identifier: feature_flags_server_ruby - weight: 206 + weight: 207 - name: Guides url: feature_flags/guide parent: feature_flags diff --git a/content/en/feature_flags/server/php.md b/content/en/feature_flags/server/php.md new file mode 100644 index 00000000000..b9f3321035e --- /dev/null +++ b/content/en/feature_flags/server/php.md @@ -0,0 +1,340 @@ +--- +title: PHP Feature Flags +description: Set up Datadog Feature Flags for PHP applications. +further_reading: +- link: "/feature_flags/server/" + tag: "Documentation" + text: "Server-Side Feature Flags" +- link: "/tracing/trace_collection/dd_libraries/php/" + tag: "Documentation" + text: "PHP Tracing" +--- + +## Overview + +This page describes how to instrument your PHP application with the Datadog Feature Flags SDK. The PHP SDK uses the Datadog SDK's Remote Configuration to receive flag updates in real time. + +The PHP SDK provides two application APIs: + +- **Datadog PHP API**: Use `DDTrace\FeatureFlags\Client` with PHP 7 or PHP 8 applications. +- **OpenFeature adapter**: Use `DDTrace\OpenFeature\DataDogProvider` with PHP 8 applications that use the [OpenFeature][1] standard API. + +Flag evaluation is local and fast. The SDK uses locally cached configuration data, so no network requests occur during evaluation. + +## Prerequisites + +Before setting up the PHP Feature Flags SDK, ensure you have: + +- **Datadog Agent** with [Remote Configuration][2] enabled +- **Datadog [API key][3]** configured on the Agent +- **Datadog PHP SDK** `datadog/dd-trace` version 1.20.0 or later +- **Supported PHP runtime** - use PHP 7 or later with the Datadog PHP API, or PHP 8 or later with the OpenFeature adapter +- **OpenFeature PHP SDK** `open-feature/sdk` version 2.1 or later, if you use the OpenFeature adapter + +Set the following environment variables: + +{{< code-block lang="bash" >}} +# Required: Enable the feature flags provider +export DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true + +# Required: Enable Remote Configuration in the SDK +export DD_REMOTE_CONFIG_ENABLED=true + +# Required: Service identification +export DD_SERVICE= +export DD_ENV= +export DD_VERSION= + +# Required for flag evaluation metrics +export DD_METRICS_OTEL_ENABLED=true +{{< /code-block >}} + +## Installation + +Feature Flagging is provided by Application Performance Monitoring (APM). Install and configure the Datadog PHP tracer by following [Tracing PHP Applications][4]. + +If you use the OpenFeature adapter in a PHP 8 application, install the OpenFeature PHP SDK: + +{{< code-block lang="bash" >}} +composer require open-feature/sdk:^2.1 +{{< /code-block >}} + +## Initialize the SDK + +Choose the API that matches your PHP runtime and application architecture. + +### PHP 7 and PHP 8: Datadog API + +Use `DDTrace\FeatureFlags\Client` directly in PHP 7 or PHP 8 applications: + +{{< code-block lang="php" >}} +}} + +### PHP 8: OpenFeature adapter + +In PHP 8 applications, you can register Datadog as the OpenFeature provider: + +{{< code-block lang="php" >}} +setProvider(new DataDogProvider()); + +$client = $api->getClient('my-service'); +{{< /code-block >}} + +The OpenFeature provider returns default values until Remote Configuration delivers the initial flag configuration. Initialize the provider early in application startup so flag configuration has time to load before business logic evaluates flags. + +## Set the evaluation context + +Define an evaluation context that identifies the user or entity for flag targeting. The targeting key is used for consistent traffic distribution, such as percentage rollouts. Additional attributes enable targeting rules, such as "enable for users in the US" or "enable for premium tier users." + +### Datadog API + +For the Datadog PHP API, pass context as an array with `targetingKey` and `attributes` keys: + +{{< code-block lang="php" >}} +$context = [ + 'targetingKey' => 'user-123', + 'attributes' => [ + 'email' => 'user@example.com', + 'country' => 'US', + 'tier' => 'premium', + 'age' => 25, + ], +]; +{{< /code-block >}} + +### OpenFeature adapter + +For the OpenFeature adapter, use the OpenFeature PHP SDK's `EvaluationContext`: + +{{< code-block lang="php" >}} +use OpenFeature\implementation\flags\Attributes; +use OpenFeature\implementation\flags\EvaluationContext; + +$context = new EvaluationContext( + 'user-123', + new Attributes([ + 'email' => 'user@example.com', + 'country' => 'US', + 'tier' => 'premium', + 'age' => 25, + ]) +); +{{< /code-block >}} + +
Evaluation context attributes must be flat primitive values: strings, numbers, and booleans. Nested arrays, objects, and null values are not sent for targeting or exposure reporting.
+ +## Evaluate flags + +After setting up the client, you can evaluate flags throughout your application. Each flag is identified by a unique string key and evaluated with a typed method that returns a value of the expected type. If the flag does not exist or cannot be evaluated, the SDK returns the provided default value. + +### Boolean flags + +Use `getBooleanValue` for flags that represent on/off or true/false conditions: + +{{< code-block lang="php" >}} +$enabled = $flags->getBooleanValue('new-checkout-flow', false, $context); + +if ($enabled) { + showNewCheckout(); +} else { + showLegacyCheckout(); +} +{{< /code-block >}} + +With OpenFeature: + +{{< code-block lang="php" >}} +$enabled = $client->getBooleanValue('new-checkout-flow', false, $context); +{{< /code-block >}} + +### String flags + +Use `getStringValue` for flags that select between variants or configuration strings: + +{{< code-block lang="php" >}} +$theme = $flags->getStringValue('ui-theme', 'light', $context); + +switch ($theme) { + case 'dark': + setDarkTheme(); + break; + case 'light': + default: + setLightTheme(); + break; +} +{{< /code-block >}} + +### Numeric flags + +For numeric flags, use `getIntegerValue` or `getFloatValue`. These methods are appropriate when a feature depends on a numeric parameter such as a limit, percentage, or multiplier: + +{{< code-block lang="php" >}} +$maxItems = $flags->getIntegerValue('cart-max-items', 20, $context); + +$discountRate = $flags->getFloatValue('discount-rate', 0.0, $context); +{{< /code-block >}} + +### Object flags + +For structured data, use `getObjectValue`. This returns a PHP array: + +{{< code-block lang="php" >}} +$config = $flags->getObjectValue('feature-config', [ + 'maxRetries' => 3, + 'timeout' => 30, +], $context); + +$maxRetries = $config['maxRetries'] ?? 3; +$timeout = $config['timeout'] ?? 30; +{{< /code-block >}} + +### Flag evaluation details + +When you need more than just the flag value, use the `getDetails` methods. These return both the evaluated value and metadata explaining the evaluation: + +{{< code-block lang="php" >}} +$details = $flags->getBooleanDetails('new-feature', false, $context); + +printf("Value: %s\n", $details->getValue() ? 'true' : 'false'); +printf("Variant: %s\n", $details->getVariant() ?? 'none'); +printf("Reason: %s\n", $details->getReason()); + +if ($details->isError()) { + printf("Error Code: %s\n", $details->getErrorCode()); + printf("Error Message: %s\n", $details->getErrorMessage()); +} +{{< /code-block >}} + +Flag details help you debug evaluation behavior and understand why a user received a given value. + +## Evaluation without context + +You can evaluate flags without providing an evaluation context. This is useful for global flags that do not require user-specific targeting: + +{{< code-block lang="php" >}} +$maintenanceMode = $flags->getBooleanValue('maintenance-mode', false); + +if ($maintenanceMode) { + http_response_code(503); + echo 'Service temporarily unavailable'; + return; +} +{{< /code-block >}} + +## Testing + +You can test against a dedicated Datadog test environment with the real Datadog provider, or replace feature flag evaluation with a test double in unit tests. + +The OpenFeature PHP SDK 2.1 does not include a built-in in-memory provider. For unit tests, wrap feature flag evaluation behind an application interface and inject a fake implementation: + +{{< code-block lang="php" filename="FeatureFlags.php" >}} +client = $client ?: new Client(); + } + + public function getBooleanValue($flagKey, $defaultValue, array $context = []) + { + return $this->client->getBooleanValue($flagKey, $defaultValue, $context); + } +} + +final class InMemoryFeatureFlagReader implements FeatureFlagReader +{ + private $flags; + + public function __construct(array $flags) + { + $this->flags = $flags; + } + + public function getBooleanValue($flagKey, $defaultValue, array $context = []) + { + return array_key_exists($flagKey, $this->flags) + ? (bool) $this->flags[$flagKey] + : $defaultValue; + } +} +{{< /code-block >}} + +Use the fake in your test setup: + +{{< code-block lang="php" filename="CheckoutTest.php" >}} +$flags = new InMemoryFeatureFlagReader([ + 'new-checkout-flow' => true, +]); + +$checkout = new CheckoutService($flags); + +self::assertTrue($checkout->usesNewCheckoutFlow('user-123')); +{{< /code-block >}} + +## Troubleshooting + +### Feature flags always return default values + +If feature flags unexpectedly always return default values, check the following: + +- Verify `DD_EXPERIMENTAL_FLAGGING_PROVIDER_ENABLED=true` is set in your application environment. +- Verify Remote Configuration is enabled in your Datadog Agent configuration. +- Ensure `DD_SERVICE` and `DD_ENV` are set and match the service and environment configured for your flag. +- Confirm your Datadog PHP SDK version includes feature flags support. +- Check that the PHP process can communicate with the Datadog Agent. + +### OpenFeature provider not found + +The OpenFeature adapter is available only for PHP 8 applications. If `DDTrace\OpenFeature\DataDogProvider` is not found: + +- Verify the application is running on PHP 8 or later. +- Verify `open-feature/sdk` is installed through Composer. +- Verify the Datadog PHP tracer version includes feature flags support. + +### Targeting rules do not match + +If targeting rules do not match as expected: + +- Set a stable `targetingKey` for the user, organization, session, or entity being evaluated. +- Pass custom targeting data under the `attributes` key when using the Datadog API. +- Use only flat primitive attributes. Nested arrays, objects, and null values are ignored. +- Verify the `DD_ENV` value appears in [{{< ui >}}Feature Flag Environments{{< /ui >}}][5]. + +### Flag evaluation metrics are missing + +Set `DD_METRICS_OTEL_ENABLED=true` to enable the `feature_flag.evaluations` counter metric. Each evaluation records a count tagged with the flag key, provider name, result variant, and evaluation reason. Error evaluations also include an error type. + +## Further reading + +{{< partial name="whats-next/whats-next.html" >}} + +[1]: https://openfeature.dev/ +[2]: /agent/remote_config/ +[3]: /account_management/api-app-keys/#api-keys +[4]: /tracing/trace_collection/dd_libraries/php/ +[5]: /feature_flags/concepts/environments/ diff --git a/layouts/partials/feature_flags/feature_flags_server.html b/layouts/partials/feature_flags/feature_flags_server.html index 638fa459472..12a424a52ab 100644 --- a/layouts/partials/feature_flags/feature_flags_server.html +++ b/layouts/partials/feature_flags/feature_flags_server.html @@ -30,6 +30,13 @@ +
From a6e0159773688b90c92a13025798225500f2200e Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 28 May 2026 18:32:07 -0400 Subject: [PATCH 2/3] Add complete PHP feature flag examples --- content/en/feature_flags/server/php.md | 80 ++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/content/en/feature_flags/server/php.md b/content/en/feature_flags/server/php.md index b9f3321035e..4252ccf7d08 100644 --- a/content/en/feature_flags/server/php.md +++ b/content/en/feature_flags/server/php.md @@ -221,6 +221,86 @@ if ($details->isError()) { Flag details help you debug evaluation behavior and understand why a user received a given value. +## Complete examples + +The following examples combine initialization, evaluation context, typed evaluation, and evaluation details. + +### PHP 7 and PHP 8: Datadog API + +{{< code-block lang="php" >}} + 'user-123', + 'attributes' => [ + 'country' => 'US', + 'tier' => 'premium', + ], +]; + +$details = $flags->getStringDetails('checkout-copy', 'control', $context); + +if ($details->isError()) { + error_log(sprintf( + 'Flag evaluation failed: %s %s', + $details->getErrorCode(), + $details->getErrorMessage() + )); +} + +if ($details->getValue() === 'treatment') { + showTreatmentCopy(); +} else { + showControlCopy(); +} +{{< /code-block >}} + +### PHP 8: OpenFeature adapter + +{{< code-block lang="php" >}} +setProvider(new DataDogProvider()); + +$client = $api->getClient('checkout-service', '1.0.0'); +$context = new EvaluationContext( + 'user-123', + new Attributes([ + 'country' => 'US', + 'tier' => 'premium', + ]) +); + +$details = $client->getStringDetails('checkout-copy', 'control', $context); +$error = $details->getError(); + +if ($error !== null) { + error_log(sprintf( + 'Flag evaluation failed: %s %s', + $error->getResolutionErrorCode()->getValue(), + $error->getResolutionErrorMessage() + )); +} + +if ($details->getValue() === 'treatment') { + showTreatmentCopy(); +} else { + showControlCopy(); +} +{{< /code-block >}} + ## Evaluation without context You can evaluate flags without providing an evaluation context. This is useful for global flags that do not require user-specific targeting: From 8f825cc2cf5bd5f38d346fe5d6d2bb41138d880b Mon Sep 17 00:00:00 2001 From: Leo Romanovsky Date: Thu, 28 May 2026 18:34:05 -0400 Subject: [PATCH 3/3] Remove PHP feature flag telemetry mentions --- content/en/feature_flags/server/php.md | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/content/en/feature_flags/server/php.md b/content/en/feature_flags/server/php.md index 4252ccf7d08..2734ebce184 100644 --- a/content/en/feature_flags/server/php.md +++ b/content/en/feature_flags/server/php.md @@ -44,9 +44,6 @@ export DD_REMOTE_CONFIG_ENABLED=true export DD_SERVICE= export DD_ENV= export DD_VERSION= - -# Required for flag evaluation metrics -export DD_METRICS_OTEL_ENABLED=true {{< /code-block >}} ## Installation @@ -134,7 +131,7 @@ $context = new EvaluationContext( ); {{< /code-block >}} -
Evaluation context attributes must be flat primitive values: strings, numbers, and booleans. Nested arrays, objects, and null values are not sent for targeting or exposure reporting.
+
Evaluation context attributes must be flat primitive values: strings, numbers, and booleans. Nested arrays, objects, and null values are ignored.
## Evaluate flags @@ -405,10 +402,6 @@ If targeting rules do not match as expected: - Use only flat primitive attributes. Nested arrays, objects, and null values are ignored. - Verify the `DD_ENV` value appears in [{{< ui >}}Feature Flag Environments{{< /ui >}}][5]. -### Flag evaluation metrics are missing - -Set `DD_METRICS_OTEL_ENABLED=true` to enable the `feature_flag.evaluations` counter metric. Each evaluation records a count tagged with the flag key, provider name, result variant, and evaluation reason. Error evaluations also include an error type. - ## Further reading {{< partial name="whats-next/whats-next.html" >}}