Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 67 additions & 16 deletions lib/Client.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,13 +254,52 @@ public function getFeatureFlag(
bool $onlyEvaluateLocally = false,
bool $sendFeatureFlagEvents = true
): null | bool | string {
$result = $this->getFeatureFlagResult(
$key,
$distinctId,
$groups,
$personProperties,
$groupProperties,
$onlyEvaluateLocally,
$sendFeatureFlagEvents
);

return $result?->getValue();
}

/**
* Get the feature flag result including value and payload.
*
* This is the recommended method for getting feature flag data as it returns
* both the flag value and payload in a single call, while properly tracking analytics.
*
* @param string $key
* @param string $distinctId
* @param array $groups
* @param array $personProperties
* @param array $groupProperties
* @param bool $onlyEvaluateLocally
* @param bool $sendFeatureFlagEvents
* @return FeatureFlagResult|null
* @throws Exception
*/
public function getFeatureFlagResult(
string $key,
string $distinctId,
array $groups = array(),
array $personProperties = array(),
array $groupProperties = array(),
bool $onlyEvaluateLocally = false,
bool $sendFeatureFlagEvents = true
): ?FeatureFlagResult {
[$personProperties, $groupProperties] = $this->addLocalPersonAndGroupProperties(
$distinctId,
$groups,
$personProperties,
$groupProperties
);
$result = null;
$payload = null;
$featureFlagError = null;

foreach ($this->featureFlags as $flag) {
Expand Down Expand Up @@ -309,6 +348,12 @@ public function getFeatureFlag(
$result = null;
}

// Extract payload from response
$rawPayload = $response['featureFlagPayloads'][$key] ?? null;
if ($rawPayload !== null) {
$payload = json_decode($rawPayload, true);
}

if (!empty($errors)) {
$featureFlagError = implode(',', $errors);
}
Expand Down Expand Up @@ -371,13 +416,22 @@ public function getFeatureFlag(
$this->distinctIdsFeatureFlagsReported->add($key, $distinctId);
}

if (!is_null($result)) {
return $result;
if (is_null($result)) {
return null;
}

// Determine enabled and variant from result
if (is_bool($result)) {
return new FeatureFlagResult($key, $result, null, $payload);
} else {
return new FeatureFlagResult($key, true, $result, $payload);
}
return null;
}

/**
* @deprecated Use `getFeatureFlagResult()` instead which properly tracks the feature flag call,
* and includes both the flag value and payload in a single method.
*
* @param string $key
* @param string $distinctId
* @param array $groups
Expand All @@ -392,20 +446,17 @@ public function getFeatureFlagPayload(
array $personProperties = array(),
array $groupProperties = array(),
): mixed {
$results = $this->flags($distinctId, $groups, $personProperties, $groupProperties);

if (isset($results['featureFlags'][$key]) === false || $results['featureFlags'][$key] !== true) {
return null;
}

$payload = $results['featureFlagPayloads'][$key] ?? null;

if ($payload === null) {
return null;
}
$result = $this->getFeatureFlagResult(
$key,
$distinctId,
$groups,
$personProperties,
$groupProperties,
false,
false
);

# feature flag payloads are always JSON encoded strings.
return json_decode($payload, true);
return $result?->getPayload();
}

/**
Expand Down
71 changes: 71 additions & 0 deletions lib/FeatureFlagResult.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<?php

namespace PostHog;

/**
* Represents the result of a feature flag evaluation, including both the value and payload.
*/
class FeatureFlagResult
{
private string $key;
private bool $enabled;
private ?string $variant;
private mixed $payload;

public function __construct(
string $key,
bool $enabled,
?string $variant = null,
mixed $payload = null
) {
$this->key = $key;
$this->enabled = $enabled;
$this->variant = $variant;
$this->payload = $payload;
}

/**
* Get the feature flag key.
*/
public function getKey(): string
{
return $this->key;
}

/**
* Whether the flag is enabled.
*/
public function isEnabled(): bool
{
return $this->enabled;
}

/**
* Get the variant value if this is a multivariate flag.
*/
public function getVariant(): ?string
{
return $this->variant;
}

/**
* Get the decoded JSON payload associated with this flag.
*/
public function getPayload(): mixed
{
return $this->payload;
}

/**
* Get the flag value in the same format as getFeatureFlag().
* Returns the variant if set, otherwise the enabled boolean.
* This matches the $feature_flag_response format.
*/
public function getValue(): bool|string
{
if ($this->variant !== null) {
return $this->variant;
}
return $this->enabled;
}
}
40 changes: 40 additions & 0 deletions lib/PostHog.php
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,46 @@ public static function getFeatureFlag(
}

/**
* Get the feature flag result including value and payload.
*
* This is the recommended method for getting feature flag data as it returns
* both the flag value and payload in a single call, while properly tracking analytics.
*
* @param string $key
* @param string $distinctId
* @param array $groups
* @param array $personProperties
* @param array $groupProperties
* @param bool $onlyEvaluateLocally
* @param bool $sendFeatureFlagEvents
* @return FeatureFlagResult|null
* @throws Exception
*/
public static function getFeatureFlagResult(
string $key,
string $distinctId,
array $groups = array(),
array $personProperties = array(),
array $groupProperties = array(),
bool $onlyEvaluateLocally = false,
bool $sendFeatureFlagEvents = true
): ?FeatureFlagResult {
self::checkClient();
return self::$client->getFeatureFlagResult(
$key,
$distinctId,
$groups,
$personProperties,
$groupProperties,
$onlyEvaluateLocally,
$sendFeatureFlagEvents
);
}

/**
* @deprecated Use getFeatureFlagResult() instead. This method does not send
* the $feature_flag_called event, leading to missing analytics.
*
* @param string $key
* @param string $distinctId
* @param array $groups
Expand Down
Loading