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 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
$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();
Loading please wait ...
Before you can download the PHP files, the dependencies should be resolved. This can take some minutes. Please be patient.