Core Library Usage
Learn how to use the Toggly PHP SDK core library in vanilla PHP or custom frameworks.
Installation
composer require toggly/feature-management-php
Basic Setup
1. Create Settings
use Toggly\FeatureManagement\Config\TogglySettings;
$settings = new TogglySettings([
'app_key' => 'your-app-key',
'environment' => 'Production',
'base_url' => 'https://definitions.toggly.io',
'use_signed_definitions' => true,
'refresh_interval' => 300, // 5 minutes
]);
2. Setup HTTP Client
You need a PSR-18 HTTP client and PSR-17 HTTP factory. For example, with Guzzle:
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use Toggly\FeatureManagement\Http\TogglyHttpClient;
$httpClient = new Client();
$requestFactory = new HttpFactory();
$togglyHttpClient = new TogglyHttpClient($httpClient, $requestFactory, $settings->getBaseUrl());
3. Initialize Services
use Toggly\FeatureManagement\Core\FeatureStateService;
use Toggly\FeatureManagement\Core\FeatureProvider;
use Toggly\FeatureManagement\Core\UsageStatsProvider;
use Toggly\FeatureManagement\Core\FeatureManager;
use Toggly\FeatureManagement\Core\MetricsService;
use Toggly\FeatureManagement\Core\MetricsRegistryService;
// State service for notifications
$featureStateService = new FeatureStateService();
// Feature provider
$featureProvider = new FeatureProvider(
$settings,
$togglyHttpClient,
$featureStateService
);
// Usage stats provider
$usageStatsProvider = new UsageStatsProvider(
$settings,
$togglyHttpClient,
null, // context provider (optional)
null // logger (optional)
);
// Metrics service
$metricsRegistryService = new MetricsRegistryService();
$metricsService = new MetricsService(
$settings,
$togglyHttpClient,
$metricsRegistryService,
null // logger (optional)
);
// Feature manager
$featureManager = new FeatureManager(
$featureProvider,
$usageStatsProvider,
$featureProvider, // secure provider (same instance)
null, // authorization service (optional)
null // logger (optional)
);
4. Use Feature Manager
if ($featureManager->isEnabled('my-feature')) {
// Feature is enabled
echo "Feature is on!";
} else {
// Feature is disabled
echo "Feature is off!";
}
Filter parity (segments + UserClaims)
Core FeatureManager evaluates shared catalog filters locally, including HTTP
segments and UserClaims. Supply context on each check:
use Toggly\FeatureManagement\Core\HttpRequestMapper;
$context = [
'identity' => $userId,
'groups' => ['beta'],
'claims' => ['role' => 'admin'], // UserClaims — from auth, not headers
'request' => [
'userAgent' => $_SERVER['HTTP_USER_AGENT'] ?? null,
'acceptLanguage' => $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? null,
'country' => 'US',
],
];
// Or map headers (cf-ipcountry / x-vercel-ip-country / cloudfront-viewer-country):
$context = HttpRequestMapper::mergeIntoContext($headers, [
'identity' => $userId,
'claims' => ['role' => $roleFromAuth],
]);
$enabled = $featureManager->isEnabled('MobileCheckout', $context);
Built-in names include AlwaysOn / AlwaysOff, Percentage, TimeWindow,
Targeting, BrowserFamily, BrowserLanguage, Country / CountryFamily,
DeviceType, OS / OperatingSystem, and UserClaims.
Unknown filters and missing segment Percentage fail closed.
Laravel classes under Toggly\Laravel\Filters\ are legacy — core evaluation
is the path above. Matrix: SDK × filter matrix.
Context Provider
Provide user context for targeting and rollouts:
use Toggly\FeatureManagement\Contracts\FeatureContextProviderInterface;
class MyContextProvider implements FeatureContextProviderInterface
{
public function getContextIdentifier(): ?string
{
return $_SESSION['user_id'] ?? null;
}
public function getContextIdentifierWithContext($context): ?string
{
if (is_array($context) && isset($context['identity'])) {
return (string) $context['identity'];
}
return $this->getContextIdentifier();
}
public function accessedInRequest(string $featureName): bool
{
$key = 'toggly_accessed_' . $featureName;
if (!empty($_SESSION[$key])) {
return true;
}
$_SESSION[$key] = true;
return false;
}
public function accessedInRequestWithContext(string $featureName, $context): bool
{
return $this->accessedInRequest($featureName);
}
}
// Use in UsageStatsProvider
$contextProvider = new MyContextProvider();
$usageStatsProvider = new UsageStatsProvider(
$settings,
$togglyHttpClient,
$contextProvider
);
Snapshot Providers
Use snapshot providers for offline support and persistence:
Cache Provider (PSR-16)
use Toggly\FeatureManagement\Storage\SnapshotProviders\CacheSnapshotProvider;
use Toggly\FeatureManagement\Storage\SnapshotSettings;
$cache = /* your PSR-16 cache implementation */;
$snapshotProvider = new CacheSnapshotProvider(
$cache,
new SnapshotSettings(['document_name' => 'toggly_features']),
86400
);
// Set on feature provider
$featureProvider->setSnapshotProvider($snapshotProvider);
Database Provider (PDO)
use Toggly\FeatureManagement\Storage\SnapshotProviders\DatabaseSnapshotProvider;
use Toggly\FeatureManagement\Storage\SnapshotSettings;
$pdo = new PDO('mysql:host=localhost;dbname=toggly', $user, $pass);
$snapshotProvider = new DatabaseSnapshotProvider(
$pdo,
new SnapshotSettings(['document_name' => 'toggly_features'])
);
// Tables are created automatically in the constructor.
// Set on feature provider
$featureProvider->setSnapshotProvider($snapshotProvider);
File Provider
use Toggly\FeatureManagement\Storage\SnapshotProviders\FileSnapshotProvider;
use Toggly\FeatureManagement\Storage\SnapshotSettings;
$snapshotProvider = new FileSnapshotProvider(
'/path/to/snapshots',
new SnapshotSettings(['document_name' => 'toggly_features'])
);
// Set on feature provider
$featureProvider->setSnapshotProvider($snapshotProvider);
State Change Notifications
Register callbacks for feature state changes:
$featureStateService->whenFeatureTurnsOn('my-feature', function () {
error_log('My feature was enabled!');
// Send notification, update cache, etc.
});
$featureStateService->whenFeatureTurnsOff('my-feature', function () {
error_log('My feature was disabled!');
// Cleanup, notify users, etc.
});
// Listen for any definition changes
$featureStateService->whenDefinitionsChange(function (array $changedFeatures) {
foreach ($changedFeatures as $featureName) {
error_log("Feature {$featureName} changed");
}
});
Usage Statistics
Usage statistics are automatically collected when using FeatureManager. To send them:
// Send collected stats
$usageStatsProvider->sendStats();
Stats include:
- Feature enabled/disabled checks
- Unique users per feature
- Actual usage tracking
Custom Metrics
Record custom metrics for experiments:
// Record a measurement (aggregated over time)
$metricsService->measure('checkout-time', 2.5);
// Record an observation (point-in-time)
$metricsService->observe('button-click', 1);
// Increment a counter
$metricsService->incrementCounter('page-views', 1);
// Send metrics
$metricsService->sendMetrics();
Secure Features
For secure features, implement an authorization service:
use Toggly\FeatureManagement\Contracts\FeatureAuthorizationServiceInterface;
class MyAuthorizationService implements FeatureAuthorizationServiceInterface
{
public function isAuthorized(string $featureName, ?array $context = null): bool
{
// Check if user has permission for this feature
$user = $context['user'] ?? null;
if (!$user) {
return false;
}
// Example: Check user role
return in_array('admin', $user['roles'] ?? []);
}
}
// Use in FeatureManager
$authService = new MyAuthorizationService();
$featureManager = new FeatureManager(
$featureProvider,
$usageStatsProvider,
$featureProvider,
$authService
);
Refreshing Features
Manually refresh feature definitions:
// Refresh from API
$featureProvider->refreshFeatures();
// Or let it auto-refresh based on refresh_interval
Error Handling
The SDK handles errors gracefully:
- Network errors: Falls back to cached/snapshot values
- Invalid responses: Uses cached values
- Signature verification failures: Logs error and uses unsigned definitions (if configured)
Always check logs for errors:
use Psr\Log\LoggerInterface;
use Monolog\Logger;
use Monolog\Handler\StreamHandler;
$logger = new Logger('toggly');
$logger->pushHandler(new StreamHandler('toggly.log', Logger::WARNING));
// Pass logger to services
$featureProvider = new FeatureProvider(
$settings,
$togglyHttpClient,
$featureStateService,
null, // snapshot provider
null, // websocket client
$logger
);
Best Practices
- Initialize Once: Create services once and reuse them
- Use Snapshot Providers: For offline support and persistence
- Handle Errors: Always provide fallback behavior
- Monitor Logs: Check logs for errors and warnings
- Refresh Periodically: Set up a cron job or scheduled task to refresh features
- Send Stats/Metrics: Regularly send usage stats and metrics
- Use Context: Provide user context for accurate targeting