PHP code example of unleash / client

1. Go to this page and download the library: Download unleash/client library. Choose the download type require.

2. Extract the ZIP file and open the index.php.

3. Add this code to the index.php.
    
        
<?php
require_once('vendor/autoload.php');

/* Start to develop here. Best regards https://php-download.com/ */

    

unleash / client example snippets




use Unleash\Client\UnleashBuilder;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();

if ($unleash->isEnabled('some-feature-name')) {
    // do something
}



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Configuration\UnleashContext;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();

$context = new UnleashContext(
    currentUserId: 'some-user-id-from-app',
    ipAddress: '127.0.0.1', // will be populated automatically from $_SERVER if needed
    sessionId: 'sess-123456', // will be populated automatically via session_id() if needed
);

// or using pre php 8 style:

$context = (new UnleashContext())
    ->setCurrentUserId('some-user-id-from-app')
    ->setIpAddress('127.0.0.1')
    ->setSessionId('sess-123456');

if ($unleash->isEnabled('some-feature', $context)) {
    // do something
}

// changing the default value for non-existent features
if ($unleash->isEnabled('nonexistent-feature', $context, true)) {
    // do something
}



use Unleash\Client\UnleashBuilder;

// both are the same
$builder = new UnleashBuilder();
$builder = UnleashBuilder::create();



use Unleash\Client\Helper\Builder\ConfigurationAware;
use Unleash\Client\Metrics\MetricsHandler;
use Unleash\Client\Configuration\UnleashConfiguration;
use Unleash\Client\DTO\Feature;
use Unleash\Client\DTO\Variant;
use Unleash\Client\UnleashBuilder;

final class CustomMetricsHandler implements MetricsHandler, ConfigurationAware
{
    private UnleashConfiguration $configuration;

    public function setConfiguration(UnleashConfiguration $configuration): void
    {
        // this method gets called automatically by the builder
        $this->configuration = $configuration;
    }

    public function handleMetrics(Feature $feature, bool $successful, Variant $variant = null): void
    {
        // the configuration object is available here
        if ($this->configuration->getInstanceId() === '...') {
            // do something
        }
    }
}

$instance = UnleashBuilder::create()
    ->withMetricsHandler(new CustomMetricsHandler())
    ->build();



use Unleash\Client\UnleashBuilder;

$builder = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id');



use Unleash\Client\UnleashBuilder;

$builder = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->withHeader('Authorization', 'my-api-key');



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Helper\Url;

$builder = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl(new Url('https://some-app-url.com', namePrefix: 'somePrefix.', tags: [
        'myTag' => 'myValue',
    ]))
    ->withInstanceId('Some instance id');



use Cache\Adapter\Filesystem\FilesystemCachePool;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
use GuzzleHttp\Client;
use GuzzleHttp\Psr7\HttpFactory;
use Unleash\Client\Stickiness\MurmurHashCalculator;
use Unleash\Client\Strategy\DefaultStrategyHandler;
use Unleash\Client\Strategy\GradualRolloutStrategyHandler;
use Unleash\Client\Strategy\IpAddressStrategyHandler;
use Unleash\Client\Strategy\UserIdStrategyHandler;
use Unleash\Client\UnleashBuilder;
use Unleash\Client\Helper\Url;

$builder = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com') // as a string
    ->withAppUrl(new Url('https://some-app-url.com', tags: ['myTag' => 'myValue'])) // or as Url instance
    ->withInstanceId('Some instance id')
    // now the optional ones
    ->withHttpClient(new Client())
    ->withRequestFactory(new HttpFactory())
    ->withCacheHandler(new FilesystemCachePool( // example with using cache/filesystem-adapter
        new Filesystem(
            new Local(sys_get_temp_dir()),
        ),
    ), 30) // the second parameter is time to live in seconds
    ->withCacheTimeToLive(60) // you can also set the cache time to live separately
    // if you don't add any strategies, by default all strategies are added
    ->withStrategies( // this example 
 


use Unleash\Client\UnleashBuilder;
use Unleash\Client\Helper\Url;

$repository = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl(new Url('https://some-app-url.com', namePrefix: 'somePrefix.', tags: [
        'myTag' => 'myValue',
    ]))
    ->withInstanceId('Some instance id')
    ->buildRepository();
$repository->refreshCache();


$builder = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com/api')
    ->withInstanceId('Some instance id')
    ->withProxy("some-proxy-key"); // <-- This is the only difference

$unleash = $builder->build();

$unleash.isEnabled("some-feature");



use Cache\Adapter\Filesystem\FilesystemCachePool;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
use Unleash\Client\UnleashBuilder;

$builder = UnleashBuilder::create()
    ->withCacheHandler(new FilesystemCachePool( // example with using cache/filesystem-adapter
        new Filesystem(
            new Local(sys_get_temp_dir()),
        ),
    ))
    ->withCacheTimeToLive(120)
    ->withStaleTtl(300)
;

// you can set the cache handler explicitly to null to revert back to autodetection

$builder = $builder
    ->withCacheHandler(null);



use Cache\Adapter\Filesystem\FilesystemCachePool;
use League\Flysystem\Adapter\Local;
use League\Flysystem\Filesystem;
use Unleash\Client\UnleashBuilder;
use Symfony\Component\Cache\Psr16Cache;
use Symfony\Component\Cache\Adapter\ArrayAdapter;

$builder = UnleashBuilder::create()
    ->withCacheHandler(new FilesystemCachePool( // example with using cache/filesystem-adapter
        new Filesystem(
            new Local(sys_get_temp_dir()),
        ),
    ))
    ->withStaleCacheHandler(new Psr16Cache(new ArrayAdapter()))
    ->withCacheTimeToLive(120)
    ->withStaleTtl(300)
;



use Unleash\Client\UnleashBuilder;

$bootstrapJson = '{"features": []}';
$bootstrapFile = 'path/to/my/file.json';
$bootstrapSplFile = new SplFileInfo('path/to/my/file.json');
$bootstrapUrl = 'https://example.com/unleash-bootstrap.json';
$bootstrapStreamWrapper = 's3://my-bucket/bootstrap.json'; // assuming you have a custom stream wrapper called 's3'
$bootstrapArray = [
    'features' => [
        [
            'enabled' => true,
            'name' => 'BootstrapDemo',
            'description' => '',
            'project' => 'default',
            'stale' => false,
            'type' => 'release',
            'variants' => [],
            'strategies' => [[ 'name' => 'default' ]],
        ],
    ],
];
$bootstrapTraversable = new class implements Iterator {
    public function current(): mixed
    {
        // todo implement method
    }
    
    public function next(): void
    {
        // todo implement method
    }
    
    public function key(): mixed
    {
        // todo implement method
    }
    
    public function valid(): bool
    {
        // todo implement method
    }
    
    public function rewind(): void
    {
        // todo implement method
    }
};
$bootstrapJsonSerializable = new class implements JsonSerializable {
    public function jsonSerialize(): array {
        // TODO: Implement jsonSerialize() method.
    }
}

// now assign them to the builder, note that each withBootstrap* method call overrides the bootstrap

$builder = UnleashBuilder::create()
    ->withBootstrap($bootstrapJson)
    ->withBootstrapFile($bootstrapFile)
    ->withBootstrapFile($bootstrapSplFile)
    ->withBootstrapUrl($bootstrapUrl)
    ->withBootstrapFile($bootstrapStreamWrapper)
    ->withBootstrap($bootstrapArray)
    ->withBootstrap($bootstrapTraversable)
    ->withBootstrap($bootstrapJsonSerializable)
    ->withBootstrap(null) // empty bootstrap
;



use Unleash\Client\Bootstrap\EmptyBootstrapProvider;
use Unleash\Client\Bootstrap\FileBootstrapProvider;
use Unleash\Client\Bootstrap\JsonBootstrapProvider;
use Unleash\Client\Bootstrap\JsonSerializableBootstrapProvider;
use Unleash\Client\UnleashBuilder;

// using variables defined in previous example, again each call overrides the last bootstrap provider

$builder = UnleashBuilder::create()
    ->withBootstrapProvider(new JsonBootstrapProvider($bootstrapJson))
    ->withBootstrapProvider(new FileBootstrapProvider($bootstrapFile))
    ->withBootstrapProvider(new FileBootstrapProvider($bootstrapSplFile))
    ->withBootstrapProvider(new FileBootstrapProvider($bootstrapUrl))
    ->withBootstrapProvider(new FileBootstrapProvider($bootstrapStreamWrapper))
    ->withBootstrapProvider(new JsonSerializableBootstrapProvider($bootstrapArray))
    ->withBootstrapProvider(new JsonSerializableBootstrapProvider($bootstrapTraversable))
    ->withBootstrapProvider(new JsonSerializableBootstrapProvider($bootstrapJsonSerializable))
    ->withBootstrapProvider(new EmptyBootstrapProvider()) // equivalent to ->withBootstrap(null)
;



use Unleash\Client\Bootstrap\CompoundBootstrapProvider;
use Unleash\Client\Bootstrap\FileBootstrapProvider;
use Unleash\Client\Bootstrap\JsonSerializableBootstrapProvider;
use Unleash\Client\UnleashBuilder;

// using variables defined in first example

$provider = new CompoundBootstrapProvider(
    new FileBootstrapProvider($bootstrapUrl),
    new FileBootstrapProvider($bootstrapFile),
    new JsonSerializableBootstrapProvider($bootstrapArray),
);

// All providers in compound bootstrap provider will be tried one by one in the order they were assigned until
// at least one returns something.

// If no provider returns non-null value, the compound provider itself returns null.

// If an exception is thrown in any of the inner providers it's ignored and next provider is tried.

// If an exception was thrown in any of the inner providers and no other provider returned any value, the exceptions
// from inner providers are thrown using a CompoundException, you can get the exceptions by calling ->getExceptions()
// on it.

$builder = UnleashBuilder::create()
    ->withBootstrapProvider($provider);



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Bootstrap\BootstrapProvider;

final class MyBootstrapProvider implements BootstrapProvider
{
    public function getBootstrap() : array|JsonSerializable|Traversable|null
    {
        // TODO: Implement getBootstrap() method.
    }
}

$builder = UnleashBuilder::create()
    ->withBootstrapProvider(new MyBootstrapProvider());



use Unleash\Client\UnleashBuilder;

$unleash = UnleashBuilder::create()
    ->withBootstrap('{}')
    ->withFetchingEnabled(false) // here we disable communication with Unleash server
    ->withCacheTimeToLive(0) // disable the caching layer to always get a fresh bootstrap
    ->build();



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Configuration\UnleashContext;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();

// without context, using the auto detected IP
$enabled = $unleash->isEnabled('some-feature');

// with context
$context = new UnleashContext(ipAddress: $_SERVER['HTTP_X_FORWARDED_FOR']);
// or pre php 8 style
$context = (new UnleashContext())
    ->setIpAddress($_SERVER['HTTP_X_FORWARDED_FOR']);
$enabled = $unleash->isEnabled('some-feature', $context);



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Configuration\UnleashContext;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();

$context = new UnleashContext(currentUserId: 'some-user-id');
$enabled = $unleash->isEnabled('some-feature', $context);



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Configuration\UnleashContext;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();

// assume the feature uses the default type which means that it will default to either session id (if session is started)
// or randomly
$unleash->isEnabled('some-feature');

// still using the default strategy but this time with user id (which is the first to be used if present)
$context = new UnleashContext(currentUserId: 'some-user-id');
$unleash->isEnabled('some-feature', $context);

// let's start the session to ensure the session id is used
session_start();
$unleash->isEnabled('some-feature');

// or you can provide your own session id
$context = new UnleashContext(sessionId: 'sess-123456');
$unleash->isEnabled('some-feature', $context);

// assume the feature is set to use the user id, the first call returns false (no context given), the second
// one returns true/false based on the user id
$unleash->isEnabled('some-feature');
$context = new UnleashContext(currentUserId: 'some-user-id');
$unleash->isEnabled('some-feature', $context);

// the same goes for session, assume the session isn't started yet and the feature is set to use the session type
$unleash->isEnabled('some-feature'); // returns false because no session is available

$context = new UnleashContext(sessionId: 'some-session-id');
$unleash->isEnabled('some-feature', $context); // works because you provided the session id manually

session_start();
$unleash->isEnabled('some-feature'); // works because the session is started

// lastly you can force the feature to use the random type which always works
$unleash->isEnabled('some-feature');



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Configuration\UnleashContext;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();

// context with custom hostname
$context = new UnleashContext(hostname: 'My-Cool-Hostname');
$enabled = $unleash->isEnabled('some-feature', $context);

// without custom hostname, defaults to gethostname() result or null
$enabled = $unleash->isEnabled('some-feature');



use Unleash\Client\ContextProvider\UnleashContextProvider;
use Unleash\Client\Configuration\UnleashContext;
use Unleash\Client\UnleashBuilder;

final class MyContextProvider implements UnleashContextProvider 
{
    public function getContext(): Context
    {
        $context = new UnleashContext();
        $context->setCurrentUserId('user id from my app');
        
        return $context;     
    }
}

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    // here we set the custom provider
    ->withContextProvider(new MyContextProvider())
    ->build();

if ($unleash->isEnabled('someFeature')) { // this call will use your context provider with the provided user id

}



use Unleash\Client\Strategy\AbstractStrategyHandler;
use Unleash\Client\DTO\Strategy;
use Unleash\Client\Configuration\Context;
use Unleash\Client\Strategy\DefaultStrategyHandler;

class AprilFoolsStrategy extends AbstractStrategyHandler
{
    public function __construct(private DefaultStrategyHandler $original)
    {
    }
    
    public function getStrategyName() : string
    {
        return 'aprilFools';
    }
    
    public function isEnabled(Strategy $strategy, Context $context) : bool
    {
        $date = new DateTimeImmutable();
        if ((int) $date->format('n') === 4 && (int) $date->format('j') === 1) {
            return (bool) random_int(0, 1);
        }
        
        return $this->original->isEnabled($strategy, $context);
    }
}



use Unleash\Client\UnleashBuilder;
use Unleash\Client\Strategy\IpAddressStrategyHandler;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->withStrategy(new AprilFoolsStrategy()) // this will append your strategy to the existing list
    ->build();

// if you want to replace all strategies, use withStrategies() instead

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->withStrategies(new AprilFoolsStrategy(), new IpAddressStrategyHandler())
    // now the unleash object will have only the two strategies
    ->build();



use Unleash\Client\DTO\DefaultVariant;
use Unleash\Client\UnleashBuilder;
use Unleash\Client\Configuration\UnleashContext;
use Unleash\Client\Enum\VariantPayloadType;
use Unleash\Client\DTO\DefaultVariantPayload;

$unleash = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->withInstanceId('Some instance id')
    ->build();
    
$variant = $unleash->getVariant('nonexistentFeature');
assert($variant->isEnabled() === false);

// getVariant() does isEnabled() call in the background meaning that it will return the default falsy variant
// whenever isEnabled() returns false
$variant = $unleash->getVariant('existingFeatureThatThisUserDoesNotHaveAccessTo');
assert($variant->isEnabled() === false);

$variant = $unleash->getVariant('someFeature', new UnleashContext(currentUserId: '123'));
if ($variant->isEnabled()) {
    $payload = $variant->getPayload();
    if ($payload !== null) {
        if ($payload->getType() === VariantPayloadType::JSON) {
            $jsonData = $payload->fromJson();
        }
        $stringPayload = $payload->getValue();
    }
}

// providing custom default variant

$variant = $unleash->getVariant('nonexistentFeature', fallbackVariant: new DefaultVariant(
    'variantName',
    enabled: true,
    payload: new DefaultVariantPayload(VariantPayloadType::STRING, 'somePayload'),
));
assert($variant->getPayload()->getValue() === 'somePayload');



use Unleash\Client\UnleashBuilder;

$unleash = UnleashBuilder::create()
    ->withAppName('Some App Name')
    ->withAppUrl('https://somewhere.com')
    ->withInstanceId('some-instance-id')
    ->withAutomaticRegistrationEnabled(false)
    ->build();

// event though the client will not attempt to register, you can still use isEnabled()
$unleash->isEnabled('someFeature');

// if you want to register manually
$unleash->register();

// you can call the register method multiple times, the Unleash server doesn't mind
$unleash->register();
$unleash->register();



use Unleash\Client\UnleashBuilder;

$unleash = UnleashBuilder::create()
    ->withAppName('Some App Name')
    ->withAppUrl('https://somewhere.com')
    ->withInstanceId('some-instance-id')
    ->withMetricsEnabled(false) // turn off metric sending
    ->withMetricsEnabled(true) // turn on metric sending
    ->withMetricsInterval(10_000) // interval in milliseconds (10 seconds)
    ->withMetricsCacheHandler(new Psr16Cache(new RedisAdapter())) // use custom cache handler for metrics, defaults to standard cache handler
    ->build();

// the metric will be collected but not sent immediately
$unleash->isEnabled('test');
sleep(10);
// now the metrics will get sent
$unleash->isEnabled('test');



use GuzzleHttp\Client;
use GuzzleHttp\Handler\CurlHandler;
use GuzzleHttp\HandlerStack;
use GuzzleHttp\Middleware;
use Psr\Http\Message\RequestInterface;
use Unleash\Client\UnleashBuilder;

// any callable is valid, it may be a function reference, anonymous function or an invokable class

// example invokable class
final class AddHeaderMiddleware
{
    public function __construct(
        private readonly string $headerName,
        private readonly string $value,
    ) {
    }

    public function __invoke(RequestInterface $request): RequestInterface
    {
        return $request->withHeader($this->headerName, $this->value);
    }
}

// example anonymous function
$addHeaderMiddleware = fn (string $headerName, string $headerValue)
    => fn(RequestInterface $request)
        => $request->withHeader($headerName, $headerValue);

// create a handler stack that holds information about all middlewares
$stack = HandlerStack::create(new CurlHandler());
// mapRequest is a helper that simplifies modifying request
$stack->push(Middleware::mapRequest(new AddHeaderMiddleware('X-My-Header', 'Some-Value')));
// or with lambda
$stack->push(Middleware::mapRequest($addHeaderMiddleware('X-My-Header2', 'Some-Value')));
// assign the stack with middlewares as a handler
$httpClient = new Client(['handler' => $stack]);

$unleash = UnleashBuilder::create()
    ->withHttpClient($httpClient) // assign the custom http client
    ->withAppName('My-App')
    ->withInstanceId('My-Instance')
    ->withAppUrl('http://localhost:4242')
    ->build();

// now every http request will have X-My-Header header with value Some-Value
$unleash->isEnabled('some-feature');



use Unleash\Client\UnleashBuilder;

$gitlabUnleash = UnleashBuilder::createForGitlab()
    ->withInstanceId('H9sU9yVHVAiWFiLsH2Mo') // generated in GitLab
    ->withAppUrl('https://git.example.com/api/v4/feature_flags/unleash/1')
    ->withGitlabEnvironment('Production')
    ->build();

// the above is equivalent to
$gitlabUnleash = UnleashBuilder::create()
    ->withInstanceId('H9sU9yVHVAiWFiLsH2Mo')
    ->withAppUrl('https://git.example.com/api/v4/feature_flags/unleash/1')
    ->withGitlabEnvironment('Production')
    ->withAutomaticRegistrationEnabled(false)
    ->withMetricsEnabled(false)
    ->build();