Skip to main content

Search Order

The dispatcher can search for and execute handlers in different orders depending on your use case. The search order determines how the dispatcher iterates through selectors and feature flags to find matches.

Available Search Orders

The SearchOrder enum provides three strategies:

  • SearchOrder::Selector (Default) - Iterate by the order selectors were added
  • SearchOrder::FeatureFlags - Iterate by the order feature flags were defined
  • SearchOrder::Custom - Iterate by a custom list of specific flags

Choosing the Right Order

OrderWhen to UsePerformance Benefit
SearchOrder::SelectorFewer selectors than feature flagsReduces iterations over selectors
SearchOrder::FeatureFlagsFewer feature flags than selectorsReduces iterations over flags
SearchOrder::CustomWant to check only specific flagsLimits scope to relevant flags only

SearchOrder::Selector (Default)

Iterates through selectors in the order they were added to the dispatcher:

use ByJG\FeatureFlag\SearchOrder;
use ByJG\FeatureFlag\FeatureFlagDispatcher;

$dispatcher = new FeatureFlagDispatcher();

// Add selectors
$dispatcher->add($selector1);
$dispatcher->add($selector2);
$dispatcher->add($selector3);

// Use default Selector order (explicit - not required)
$dispatcher->withSearchOrder(SearchOrder::Selector);

// Dispatches in order: selector1 → selector2 → selector3
$dispatcher->dispatch();

Best for:

  • Small number of selectors
  • Priority-based execution
  • Most common use case

SearchOrder::FeatureFlags

Iterates through feature flags in the order they were defined:

use ByJG\FeatureFlag\SearchOrder;
use ByJG\FeatureFlag\FeatureFlags;
use ByJG\FeatureFlag\FeatureFlagDispatcher;

// Define flags
FeatureFlags::addFlag('flag-a', 'value1');
FeatureFlags::addFlag('flag-b', 'value2');
FeatureFlags::addFlag('flag-c', 'value3');

$dispatcher = new FeatureFlagDispatcher();

// Add many selectors
$dispatcher->add($selectorForFlagA);
$dispatcher->add($selectorForFlagB);
$dispatcher->add($anotherSelectorForFlagA);

// Use FeatureFlags order
$dispatcher->withSearchOrder(SearchOrder::FeatureFlags);

// Dispatches in flag order: flag-a → flag-b → flag-c
$dispatcher->dispatch();

Best for:

  • Many selectors for few flags
  • Flag-priority scenarios
  • When flag order matters more than selector order

SearchOrder::Custom

Limits execution to a specific subset of feature flags:

use ByJG\FeatureFlag\SearchOrder;
use ByJG\FeatureFlag\FeatureFlags;
use ByJG\FeatureFlag\FeatureFlagDispatcher;

// Define many flags
FeatureFlags::addFlag('feature-1', 'on');
FeatureFlags::addFlag('feature-2', 'on');
FeatureFlags::addFlag('feature-3', 'on');
FeatureFlags::addFlag('feature-4', 'on');
FeatureFlags::addFlag('feature-5', 'on');

$dispatcher = new FeatureFlagDispatcher();

// Add selectors for all features
$dispatcher->add($selector1);
$dispatcher->add($selector2);
$dispatcher->add($selector3);
$dispatcher->add($selector4);
$dispatcher->add($selector5);

// Only check feature-2 and feature-4 (in that order)
$dispatcher->withSearchOrder(SearchOrder::Custom, ['feature-2', 'feature-4']);

// Only selectors matching feature-2 and feature-4 execute
$dispatcher->dispatch();

Best for:

  • Conditional feature execution
  • Testing specific flags
  • Performance optimization when many flags exist but only a few matter
  • Runtime flag filtering

Setting the Search Order

Use the withSearchOrder() method before dispatching:

$dispatcher->withSearchOrder(SearchOrder::FeatureFlags);
$dispatcher->dispatch();
warning

When using SearchOrder::Custom, you must provide the array of flag names as the second parameter. An exception is thrown if the array is empty or if you provide flags without using Custom mode.

Examples

Priority-Based Execution

// High priority handlers first
$dispatcher->add($criticalHandler);
$dispatcher->add($importantHandler);
$dispatcher->add($normalHandler);

$dispatcher->withSearchOrder(SearchOrder::Selector); // Default
$dispatcher->dispatch();

Feature-First Execution

// Define flags in priority order
FeatureFlags::addFlag('security', 'enabled');
FeatureFlags::addFlag('performance', 'enabled');
FeatureFlags::addFlag('ui', 'enabled');

$dispatcher->withSearchOrder(SearchOrder::FeatureFlags);
$dispatcher->dispatch();
// Executes handlers in flag definition order

Selective Feature Testing

// Only test payment-related features
$dispatcher->withSearchOrder(SearchOrder::Custom, [
'stripe-payment',
'paypal-payment',
'invoice-generation'
]);

$dispatcher->dispatch();
// Only handlers for these three flags execute

Performance Considerations

Selector Order (Default)

  • Iterations: Number of selectors
  • Best when: selectors < flags
  • Worst case: O(selectors × flags)

FeatureFlags Order

  • Iterations: Number of flags
  • Best when: flags < selectors
  • Worst case: O(flags × selectors)

Custom Order

  • Iterations: Number of custom flags
  • Best when: You only need a subset
  • Worst case: O(custom_flags × selectors)

Error Handling

// ❌ Wrong - Custom requires flags array
try {
$dispatcher->withSearchOrder(SearchOrder::Custom);
} catch (\InvalidArgumentException $e) {
echo "Must provide flags when using Custom search order";
}

// ❌ Wrong - Can't provide flags without Custom
try {
$dispatcher->withSearchOrder(SearchOrder::Selector, ['flag1']);
} catch (\InvalidArgumentException $e) {
echo "Must not provide flags when not using Custom search order";
}

// ✅ Correct
$dispatcher->withSearchOrder(SearchOrder::Custom, ['flag1', 'flag2']);

See Also