php 58 lines · 8 steps

How a feature flag evaluator decides

A flag evaluator resolves an on/off decision from static config, targeting rules, and a stable percentage rollout.

Explained by highlit
1<?php
2 
3namespace App\FeatureFlags;
4 
5class FlagEvaluator
6{
7 public function __construct(private array $flags)
8 {
9 }
10 
11 public function isEnabled(string $flag, array $context = []): bool
12 {
13 $config = $this->flags[$flag] ?? null;
14 
15 if ($config === null || ($config['enabled'] ?? false) === false) {
16 return false;
17 }
18 
19 foreach ($config['rules'] ?? [] as $rule) {
20 if ($this->matchesRule($rule, $context)) {
21 return $rule['serve'] ?? true;
22 }
23 }
24 
25 $rollout = $config['rollout'] ?? 100;
26 
27 return $this->withinRollout($flag, $context['user_id'] ?? '', $rollout);
28 }
29 
30 private function matchesRule(array $rule, array $context): bool
31 {
32 $value = $context[$rule['attribute']] ?? null;
33 
34 return match ($rule['operator']) {
35 'in' => in_array($value, $rule['values'], true),
36 'not_in' => !in_array($value, $rule['values'], true),
37 'equals' => $value === $rule['value'],
38 'greater_than' => is_numeric($value) && $value > $rule['value'],
39 'ends_with' => is_string($value) && str_ends_with($value, $rule['value']),
40 default => false,
41 };
42 }
43 
44 private function withinRollout(string $flag, string $userId, int $percentage): bool
45 {
46 if ($percentage >= 100) {
47 return true;
48 }
49 
50 if ($percentage <= 0 || $userId === '') {
51 return false;
52 }
53 
54 $bucket = crc32($flag . ':' . $userId) % 100;
55 
56 return $bucket < $percentage;
57 }
58}
01 / 01
STEP 01

Walkthrough

Space play step click any line
Three takeaways
  1. 1Layering a global switch, targeting rules, and a percentage rollout lets one method serve nuanced flag decisions.
  2. 2Hashing a stable key like flag plus user id gives consistent bucketing so a user always lands the same way.
  3. 3The null-coalescing operator and match expression keep config-driven logic terse and safe against missing keys.

Related explainers

Share this explainer

Here's the card — post it anywhere.

How a feature flag evaluator decides — share card
Made with highlit — turn any snippet into a walkthrough like this in about a minute.
Explain your code