A PHP implementation of the Unleash protocol aka Feature Flags in GitLab

Overview

Tests Tests (7.x) Coverage Status

A PHP implementation of the Unleash protocol aka Feature Flags in GitLab.

You may also be interested in the Symfony Bundle for this package.

This implementation conforms to the official Unleash standards and implements all of Unleash features.

Unleash allows you to gradually release your app's feature before doing a full release based on multiple strategies like releasing to only specific users or releasing to a percentage of your user base. Read more in the above linked documentations.

Installation

composer require unleash/client

Requires PHP 7.3 or newer.

You will also need some implementation of PSR-18 and PSR-17, for example Guzzle and PSR-16, for example Symfony Cache. Example:

composer require unleash/client guzzlehttp/guzzle symfony/cache

or

composer require unleash/client symfony/http-client nyholm/psr7 symfony/cache

Usage

The basic usage is getting the Unleash object and checking for a feature:



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
}

You can (and in some cases you must) also provide a context object. If the feature doesn't exist on the server you will get false from isEnabled(), but you can change the default value to true.



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
}

Builder

The builder contains many configuration options, and it's advised to always use the builder to construct an Unleash instance. The builder is immutable.

The builder object can be created using the create() static method or by using its constructor:



use Unleash\Client\UnleashBuilder;

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

Required parameters

The app name, instance id and app url are required as per the specification.



use Unleash\Client\UnleashBuilder;

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

If you're using Unleash v4 you also need to specify authorization key (API key), you can do so with custom header.



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');

Optional parameters

Some optional parameters can be set, these include:

  • http client implementation
  • request factory implementation
  • cache implementation (PSR-16)
  • cache ttl
  • available strategies
  • http headers

If you use guzzlehttp/guzzle or symfony/http-client (in combination with nyholm/psr7), the http client and request factory will be created automatically, otherwise you need to provide an implementation on your own.

If you use symfony/cache or cache/filesystem-adapter as your cache implementation, the cache handler will be created automatically, otherwise you need to provide some implementation on your own.



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;

$builder = UnleashBuilder::create()
    ->withAppName('Some app name')
    ->withAppUrl('https://some-app-url.com')
    ->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 includes all available strategies
        new DefaultStrategyHandler(),
        new GradualRolloutStrategyHandler(new MurmurHashCalculator()),
        new IpAddressStrategyHandler(),
        new UserIdStrategyHandler(),
    )
    // add headers one by one, if you specify a header with the same name multiple times it will be replaced by the
    // latest value
    ->withHeader('My-Custom-Header', 'some-value')
    ->withHeader('Some-Other-Header', 'some-other-value')
    // you can specify multiple headers at the same time, be aware that this REPLACES all the headers
    ->withHeaders([
        'Yet-Another-Header' => 'and-another-value',
    ]);

Caching

It would be slow to perform a http request every time you check if a feature is enabled, especially in popular apps. That's why this library has built-in support for PSR-16 cache implementations.

If you don't provide any implementation and default implementation exists, it's used, otherwise you'll get an exception. You can also provide a TTL which defaults to 30 seconds.

Cache implementations supported out of the box (meaning you don't need to configure anything):



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);

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

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

Strategies

Unleash servers can use multiple strategies for enabling or disabling features. Which strategy gets used is defined on the server. This implementation supports all non-deprecated v4 strategies. More here.

Default strategy

This is the simplest of them and simply always returns true if the feature defines default as its chosen strategy and doesn't need any context parameters.

IP address strategy

Enables feature based on the IP address. Takes current user's IP address from the context object. You can provide your own IP address or use the default ($_SERVER['REMOTE_ADDR']). Providing your own is especially useful if you're behind proxy and thus REMOTE_ADDR would return your proxy server's IP address instead.



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);

User ID strategy

Enables feature based on the user ID. The user ID can be any string. You must always provide your own user id via 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);

Gradual rollout strategy

Also known as flexible rollout. Allows you to enable feature for only a percentage of users based on their user id, session id or randomly. The default is to try in this order: user id, session id, random.

If you specify the user id type on your Unleash server, you must also provide the user id via context, same as in the User ID strategy. Session ID can also be provided via context, it defaults to the current session id via session_id() call.

This strategy requires a stickiness calculator that transforms the id (user, session or random) into a number between 1 and 100. You can provide your own or use the default \Unleash\Client\Stickiness\MurmurHashCalculator



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');

Hostname strategy

This strategy allows you to match against a list of server hostnames (which are not the same as http hostnames).

If you don't specify a hostname in context, it defaults to the current hostname using gethostname().



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');

Note: This library also implements some deprecated strategies, namely gradualRolloutRandom, gradualRolloutSessionId and gradualRolloutUserId which all alias to the Gradual rollout strategy.

Context provider

Manually creating relevant context can get tiring real fast. Luckily you can create your own context provider that will do it for you!



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

}

Custom strategies

To implement your own strategy you need to create a class implementing StrategyHandler (or AbstractStrategyHandler which contains some useful methods). Then you need to instruct the builder to use your custom strategy.



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);
    }
}

Now you must instruct the builder to use your new strategy



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();

Variants

You can use multiple variants of one feature, for example for A/B testing. If no variant matches or the feature doesn't have any variants, a default one will be returned which returns false for isEnabled(). You can also provide your own default variant.

Variant may or may not contain a payload.



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');

Client registration

By default, the library automatically registers itself as an application in the Unleash server. If you want to prevent this, use withAutomaticRegistrationEnabled(false) in the builder.



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();

Metrics

By default, this library sends metrics which are simple statistics about whether user was granted access or not.

The metrics will be bundled and sent once the bundle created time crosses the configured threshold. By default this threshold is 30,000 milliseconds (30 seconds) meaning that when a new bundle gets created it won't be sent sooner than in 30 seconds. That doesn't mean it's guaranteed that the metrics will be sent every 30 seconds, it only guarantees that the metrics won't be sent sooner.

Example:

  1. user visits your site and this sdk gets triggered, no metric has been sent
  2. after five seconds user visits another page where again this sdk gets triggered, no metric sent
  3. user waits one minute before doing anything, no one else is accessing your site
  4. after one minute user visits another page, the metrics have been sent to the Unleash server

In the example above the metric bundle gets sent after 1 minute and 5 seconds because there was no one to trigger the code.



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)
    ->build();

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

Constraints

Constraints are supported by this SDK and will be handled correctly by Unleash::isEnabled() if present.

GitLab specifics

  • In GitLab you have to use the provided instance id, you cannot create your own.
  • No authorization header is necessary.
  • Instead of app name you need to specify the GitLab environment.
    • For this purpose you can use withGitlabEnvironment() method in builder, it's an alias to withAppName() but communicates the intent better.
  • GitLab doesn't use registration system, you can set the SDK to disable automatic registration and save one http call.
  • GitLab doesn't read metrics, you can set the SDK to disable sending them and save some http calls.


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();
Comments
  • Could not find package unleash/unleash-client.

    Could not find package unleash/unleash-client.

    Tried to install unleash on my project and getting this title error

    Also, not found in packagist: https://packagist.org/search.json?q=unleash/unleash-client

    Exception trace:
     () at phar:///usr/local/bin/composer/src/Composer/Command/InitCommand.php:792  
     Composer\Command\InitCommand->findBestVersionAndNameForPackage() at phar:///usr/local/bin/composer/src/Composer/Command/InitCommand.php:416
     Composer\Command\InitCommand->determineRequirements() at phar:///usr/local/bin/composer/src/Composer/Command/RequireCommand.php:163
     Composer\Command\RequireCommand->execute() at phar:///usr/local/bin/composer/vendor/symfony/console/Command/Command.php:245
     Symfony\Component\Console\Command\Command->run() at phar:///usr/local/bin/composer/vendor/symfony/console/Application.php:835
     Symfony\Component\Console\Application->doRunCommand() at phar:///usr/local/bin/composer/vendor/symfony/console/Application.php:185
     Symfony\Component\Console\Application->doRun() at phar:///usr/local/bin/composer/src/Composer/Console/Application.php:281
     Composer\Console\Application->doRun() at phar:///usr/local/bin/composer/vendor/symfony/console/Application.php:117
     Symfony\Component\Console\Application->run() at phar:///usr/local/bin/composer/src/Composer/Console/Application.php:113
     Composer\Console\Application->run() at phar:///usr/local/bin/composer/bin/composer:61
     require() at /usr/local/bin/composer:24
    
    opened by mlg404 5
  • [Feature]: Support for PHP 7.0

    [Feature]: Support for PHP 7.0

    Is there an existing issue for this?

    • [X] I have searched the existing issues

    Describe the new feature

    Hello, first of all I wanted to say that I appreciate the work done for the Unleash community and all of the effort that went into this SDK. Now onto the issue, are there any plans to eventually support PHP 7.0? If not, are there any technical reasons for it (in case someone tries to add the support themselves)?

    Is your feature request related to a problem? (optional)

    Currently unable to use this client for a project because of the PHP version (changing the project PHP version is unfortunately not possible)

    Describe alternatives you've considered (optional)

    No response

    Additional context (optional)

    No response

    opened by MarcosRolando 4
  • Sporadic cache errors errors when reporting metrics

    Sporadic cache errors errors when reporting metrics

    Hi, I have been experiencing sporadic errors in https://github.com/Unleash/unleash-client-php/blob/v1.2.074/src/Metrics/DefaultMetricsHandler.php#L40 while using https://packagist.org/packages/cache/redis-adapter as cache adapter:

    TypeError · Return value of Unleash\Client\Metrics\DefaultMetricsHandler::getOrCreateBucket() must be an instance of Unleash\Client\Metrics\MetricsBucket, null returned
    

    Metrics get reported regardless and are visible in Unleash, but this error persistently occurs without any specific pattern.

    opened by thedotedge 4
  • Use php-http/discovery to find PSR-17/18 implementations

    Use php-http/discovery to find PSR-17/18 implementations

    This project relies on PSR-17 request factories and PSR-18 HTTP clients to perform HTTP requests. It will load Guzzle and Symfony implementations if they exist, otherwise the user is required to provide their own.

    Let's use php-http/discovery to load more PSR-17/18 implementations automatically. This will reduce the need for users to configure their own PSR-17/18 implementations manually.

    opened by Xenonym 4
  • Bug: stale data cache is not loaded when HTTP communication fails with 4xx or 5xx codes

    Bug: stale data cache is not loaded when HTTP communication fails with 4xx or 5xx codes

    Is there an existing issue for this?

    • [X] I have searched the existing issues

    Describe the bug

    The docs state:

    Stale data cache is used when http communication fails while fetching feature list from the server.

    The DefaultUnleashRepository only fetches stale cache when an exception is thrown:

                    try {
                        $response = $this->httpClient->sendRequest($request);
                        if ($response->getStatusCode() === 200) {
                            $data = $response->getBody()->getContents();
                            $this->setLastValidState($data);
                        }
                    } catch (Exception $exception) {
                        $this->configuration->getEventDispatcherOrNull()?->dispatch(
                            new FetchingDataFailedEvent($exception),
                            UnleashEvents::FETCHING_DATA_FAILED,
                        );
                        $data = $this->getLastValidState();
                    }
    

    If a 4xx or 5xx code is returned, the FETCHING_DATA_FAILED event is not dispatched, and last valid state not fetched.

    The Client's sendRequest() method implements PSR-7, which expects the method to return instead of throwing in the event of a valid response but 4xx or 5xx error code. Since Unleash fails to fetch data from the server with these header codes (according to HTTP conventions), this should be fixed.

    My hacky workaround was to create a new Client child class that forces it to throw on non-2xx header codes. Setting the http_errors option on the default client does not work.

    To reproduce

    1. Set up the code to use the default Unleash repository with a cache
    2. Make a request to get a response and put data in the cace
    3. Change the authorization in the configuration to something incorrect
    4. Make another request (this will cause the HTTP request to return a 401 header code)
    5. An exception is thrown

    Sample code (optional)

    No response

    Version

    v1.8.081

    Expected behavior

    Stale cache should be loaded, but it's not.

    Logs (optional)

    No response

    Additional context (optional)

    No response

    bug 
    opened by eblanshey 3
  • Bug: stub for EventDispatcher Interface error

    Bug: stub for EventDispatcher Interface error

    Is there an existing issue for this?

    • [X] I have searched the existing issues

    Describe the bug

    We use laravel 5.6 with symfony/http-kernel:^4.0 When we run composer dumpautoload this error is thrown:

    Declaration of Unleash\Client\Helper\EventDispatcher::addListener(string $eventName, callable $listen
      er, int $priority = 0): void must be compatible with Symfony\Component\EventDispatcher\EventDispatche
      rInterface::addListener($eventName, $listener, $priority = 0)
    

    To reproduce

    1. must use laravel 5.6
    2. install unleash 1.7 (event dispatcher requirements not installed)
    3. run composer dumpautoload

    Sample code (optional)

    No response

    Version

    1.7.072

    Expected behavior

    no errors since we wont be using the event dispatcher.

    Logs (optional)

    No response

    Additional context (optional)

    No response

    bug 
    opened by angeloinqbyte 3
  • meta: add external PRs to project board

    meta: add external PRs to project board

    Description

    The pull_request hook runs in the context of the proposed changes. That means that for forks, this action won't have access to the required secrets for it to complete. As such, PRs from outside contributors won't work correctly.

    The pull_request_target hook, however, runs in the context of the target branch, and thus has all the permissions it needs. The github docs for this hook also indicate that this is the way to go:

    This event allows your workflow to do things like label or comment on pull requests from forks. Avoid using this event if you need to build or run code from the pull request.

    Interesting note for PRs

    It seems that when this change is proposed as a PR, the expected action (add new item to project board) does not run. However, this does not affect other new PRs. After merging, the pipeline works and triggers as expected, for both external and internal contributors.

    opened by thomasheartman 3
  • Add `environment` property to context

    Add `environment` property to context

    opened by fenix20113 3
  • Feat: Add stale cache

    Feat: Add stale cache

    Description

    Adds configuration for stale data cache triggered in case of http communication failure.

    Ref https://github.com/Unleash/unleash-client-symfony/issues/23 (this is part one, the other part must be done in Symfony bundle after this gets merged).

    Type of change

    • [x] New feature (non-breaking change which adds functionality)

    How Has This Been Tested?

    Please describe the tests that you ran to verify your changes.

    • [x] Unit tests
    • [x] Integration tests / Manual Tests

    Checklist:

    • [x] I have performed a self-review of my own code
    • [x] I have commented my code, particularly in hard-to-understand areas
    • [x] I have made corresponding changes to the documentation
    • [x] My changes generate no new warnings
    • [x] I have added tests that prove my fix is effective or that my feature works
    • [x] New and existing unit tests pass locally with my changes
    • [x] Any dependent changes have been merged and published in downstream modules
    opened by RikudouSage 2
  • [Bug]: symfony/event-dispatcher is required

    [Bug]: symfony/event-dispatcher is required

    Is there an existing issue for this?

    • [X] I have searched the existing issues

    Describe the bug

    Latest release added symfony/event-dispatcher as an optional dependency (according to composer.json, it is only required for dev).

    Yet the code is written in a way that symfony/event-dispatcher is required. Thus an exception is triggered when e.g. a feature flag is disabled and the autoloader cannot find the associated classes, e.g. Symfony\Contracts\EventDispatcher\Event.

    To reproduce

    1. Run Unleash without sentry/event-dispatcher
    2. Check for a disabled feature flag

    Sample code (optional)

    No response

    Version

    v1.5.081

    Expected behavior

    isEnabled() returns false instead of throwing an error or exception.

    Logs (optional)

    No response

    Additional context (optional)

    No response

    bug 
    opened by netzhuffle 2
  • Feat: Bootstrapping

    Feat: Bootstrapping

    closes #43

    Implemented according to specifications - if the request to unleash api fails it falls back to a bootstrap provider (if present).

    Also added a configuration parameter to disable fetching the api at all in which case these things are disabled:

    • fetching features
    • client registration
    • sending metrics

    If fetching is disabled and no bootstrap is provided, an exception is thrown.

    opened by RikudouSage 2
  • Feat: Add separate stale cache handler config

    Feat: Add separate stale cache handler config

    Description

    Includes a configuration to set different stale cache handler.

    Fixes #131

    Type of change

    Please delete options that are not relevant.

    • [x] New feature (non-breaking change which adds functionality)

    How Has This Been Tested?

    • [x] Unit tests
    • [x] Integration tests

    Checklist:

    • [x] I have performed a self-review of my own code
    • [x] I have commented my code, particularly in hard-to-understand areas
    • [x] I have made corresponding changes to the documentation
    • [x] My changes generate no new warnings
    • [x] I have added tests that prove my fix is effective or that my feature works
    • [x] New and existing unit tests pass locally with my changes
    • [x] Any dependent changes have been merged and published in downstream modules
    opened by RikudouSage 0
  • Feat: When Client Registration Fails on init/build, allow to proceed and use Stale Cache if it exists

    Feat: When Client Registration Fails on init/build, allow to proceed and use Stale Cache if it exists

    Is there an existing issue for this?

    • [X] I have searched the existing issues

    Describe the new feature

    It would be great if other HTTP requests fail, in our case when automatic client registration fails when initializing, Unleash wont stop and throw an error and instead allow us to proceed to use the stale cache if it exists.

    Is your feature request related to a problem? (optional)

    the HTTP request for automatic client registration returns 4xx 5xx during unleash initialization, unleash itself throws an error and hard crashes our fflag service initialization that use unleash. We dont handle this error at the moment because we expected unleash to continue building itself then allow us to use the stale cache.

    Describe alternatives you've considered (optional)

    I read we can turn off automatic client registration, would that help resolve the problem? what side effects would that have? or should we just accept and expect that when client registration happens to fail we just catch the error and handle it?

    Additional context (optional)

    Symfony\Component\HttpClient\Exception\TransportException: Empty reply from server for "https://app.unleash-hosted.com/nattier/api/client/register". in /home/forge/kryptonescort.com/vendor/symfony/http-client/Response/CurlResponse.php:334 Stack trace: #0 /home/forge/kryptonescort.com/vendor/symfony/http-client/Response/TransportResponseTrait.php(174): Symfony\Component\HttpClient\Response\CurlResponse::perform(Object(Symfony\Component\HttpClient\Internal\CurlClientState), Array) #1 /home/forge/kryptonescort.com/vendor/symfony/http-client/Response/CommonResponseTrait.php(153): Symfony\Component\HttpClient\Response\CurlResponse::stream(Array, NULL) #2 /home/forge/kryptonescort.com/vendor/symfony/http-client/Response/TransportResponseTrait.php(53): Symfony\Component\HttpClient\Response\CurlResponse::initialize(Object(Symfony\Component\HttpClient\Response\CurlResponse)) #3 /home/forge/kryptonescort.com/vendor/symfony/http-client/Psr18Client.php(100): Symfony\Component\HttpClient\Response\CurlResponse->getStatusCode() #4 /home/forge/kryptonescort.com/vendor/unleash/client/src/Client/DefaultRegistrationService.php(84): Symfony\Component\HttpClient\Psr18Client->sendRequest(Object(Nyholm\Psr7\Request)) #5 /home/forge/kryptonescort.com/vendor/unleash/client/src/DefaultUnleash.php(156): Unleash\Client\Client\DefaultRegistrationService->register(Array) #6 /home/forge/kryptonescort.com/vendor/unleash/client/src/DefaultUnleash.php(66): Unleash\Client\DefaultUnleash->register() #7 /home/forge/kryptonescort.com/vendor/unleash/client/src/UnleashBuilder.php(496): Unleash\Client\DefaultUnleash->__construct(Array, Object(Unleash\Client\Repository\DefaultUnleashRepository), Object(Unleash\Client\Client\DefaultRegistrationService), Object(Unleash\Client\Configuration\UnleashConfiguration), Object(Unleash\Client\Metrics\DefaultMetricsHandler), Object(Unleash\Client\Variant\DefaultVariantHandler)) #8 /home/forge/kryptonescort.com/app/Containers/Shared/Services/UnleashFeatureFlagService.php(70): Unleash\Client\UnleashBuilder->build()

    opened by angeloinqbyte 1
  • Feat: allow separate cache driver to be used for stale cache

    Feat: allow separate cache driver to be used for stale cache

    Is there an existing issue for this?

    • [X] I have searched the existing issues

    Describe the new feature

    There are two levels of caching currently: the 30s short cache, and the stale cache which is longer. Additionally, there is a way to provide a bootstrap file that can be used in case a request to the server fails. So in essence there are 3 ways of falling back to something if a request fails.

    A bootstrap is persistent, whereas the caches are temporary. What I would like is to have a more persistent "stale" cache, that stores the result of the latest known request. This is better than a bootstrap file that needs be manually updated with the latest feature flags.

    The stale cache that's currently implemented works well, but uses the same cache provider as the short term 30s cache. The two usages are quite different: one is for frequent requests in a cache store that is ephemeral (like Memcached and Redis with automatic eviction.) The stale cache is more long term and shouldn't be wiped out automatically with evictions, new deployments, etc -- it is used to prevent errors from bubbling up on production.

    It would be nice to provide the ability to set a separate cache driver for the stale cache, via the builder, such as with a withStaleCacheHandler() method. The stale cache handler can then use a more persistent storage such as a file or persistent Redis instance. Consider it like a way to auto-populate a bootstrap file.

    To make it backwards compatible with previous releases, the stale cache can use the regular cache provider if one is not provided.

    Is your feature request related to a problem? (optional)

    No response

    Describe alternatives you've considered (optional)

    No response

    Additional context (optional)

    No response

    opened by eblanshey 3
Releases(v1.8.282)
  • v1.8.282(Dec 12, 2022)

    What's Changed

    • Chore: Trigger tests for php 8.2 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/125
    • Chore: Update rector and rules by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/127
    • Chore: Add support for php 8.2 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/128
    • Fix: Load stale data whenever there's any http error by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/130
    • Fix duplicate tag for release script by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/134

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.8.181...v1.8.282

    Source code(tar.gz)
    Source code(zip)
  • v1.8.181(Oct 28, 2022)

    What's Changed

    • Read the response body from the start by @colinodell in https://github.com/Unleash/unleash-client-php/pull/123
    • Chore: Increase version before release by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/124

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.8.081...v1.8.181

    Source code(tar.gz)
    Source code(zip)
  • v1.8.081(Oct 14, 2022)

    What's Changed

    • Allow psr/simple-cache 3.x by @colinodell in https://github.com/Unleash/unleash-client-php/pull/120

    New Contributors

    • @colinodell made their first contribution in https://github.com/Unleash/unleash-client-php/pull/120

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.7.181...v1.8.081

    Source code(tar.gz)
    Source code(zip)
  • v1.7.181(Sep 24, 2022)

    What's Changed

    • Fix: Don't throw on older version of event dispatcher by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/113

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.7.081...v1.7.181

    Source code(tar.gz)
    Source code(zip)
  • v1.7.081(Aug 11, 2022)

    What's Changed

    • Feat: Add impression data support by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/90
    • Feat: Global segments by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/104

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.6.181...v1.7.081

    Source code(tar.gz)
    Source code(zip)
  • v1.6.181(Jul 14, 2022)

    What's Changed

    • Enhancement: Make all events extend one parent by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/101
    • Fix: Cache working for empty features by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/106

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.6.081...v1.6.181

    Source code(tar.gz)
    Source code(zip)
  • v1.6.081(Jun 27, 2022)

    What's Changed

    • Feat: Add stale cache by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/97

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.5.481...v1.6.081

    Source code(tar.gz)
    Source code(zip)
  • v1.5.481(Jun 12, 2022)

    What's Changed

    • Fix: Allow all event dispatchers by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/94

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.5.381...v1.5.481

    Source code(tar.gz)
    Source code(zip)
  • v1.5.381(May 30, 2022)

    What's Changed

    • meta: add external PRs to project board by @thomasheartman in https://github.com/Unleash/unleash-client-php/pull/91
    • docs: update return type documentation by @rlcurrall in https://github.com/Unleash/unleash-client-php/pull/92

    New Contributors

    • @rlcurrall made their first contribution in https://github.com/Unleash/unleash-client-php/pull/92

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.5.281...v1.5.381

    Source code(tar.gz)
    Source code(zip)
  • v1.5.281(May 19, 2022)

    What's Changed

    • Chore: Remove 8.1 polyfill by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/86
    • Fix: Don't throw on missing user ids by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/87
    • Fix: Don't require latest version of polyfill by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/88

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.5.181...v1.5.281

    Source code(tar.gz)
    Source code(zip)
  • v1.5.181(May 16, 2022)

    What's Changed

    • Fix: Add a stub for Event class if it's not loaded by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/84

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.5.081...v1.5.181

    Source code(tar.gz)
    Source code(zip)
  • v1.5.081(May 13, 2022)

    What's Changed

    • meta: add 'new items to project board' workflow by @thomasheartman in https://github.com/Unleash/unleash-client-php/pull/78
    • Feat: Add event system by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/77

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.4.081...v1.5.081

    Source code(tar.gz)
    Source code(zip)
  • v1.4.081(Apr 14, 2022)

    What's Changed

    • Tests: Update client specifications to latest version by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/71
    • Feat: Add name prefix and tags filters helper by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/70
    • Feat: Add support for CIDR notation in IP strategy by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/69

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.3.281...v1.4.081

    Source code(tar.gz)
    Source code(zip)
  • v1.3.281(Apr 7, 2022)

    What's Changed

    • Fix: Calling array_is_list on older versions of php by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/67
    • Chore: Increase version before release by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/68

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.3.181...v1.3.281

    Source code(tar.gz)
    Source code(zip)
  • v1.3.181(Mar 22, 2022)

    What's Changed

    • Chore: Ignore rector.72.php in export by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/60
    • Chore: Remove leftover things from previous versions by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/61
    • Docs: Add middleware documentation by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/62
    • Add tests for invalid version value and invalid operator, don't throw… by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/63
    • Fix syntax errors for php 7.2 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/64
    • Increase version before release by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/65

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.3.081...v1.3.181

    Source code(tar.gz)
    Source code(zip)
  • v1.3.081(Mar 22, 2022)

    What's Changed

    • Feat: Bootstrapping by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/44
    • Remove syntax error for php < 8 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/52
    • Remove syntax error for php < 8 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/53
    • Remove syntax error for php < 8 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/54
    • Fix 7x syntax errors by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/55
    • Fix: Use correct branch name in badge link by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/56
    • Fix JSON_THROW_ON_ERROR for php < 7.3 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/57
    • Feat: Support more constraint operators by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/47
    • Fix php 7.2 error by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/58
    • Increase SDK version by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/59

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.2.581...v1.3.081

    Source code(tar.gz)
    Source code(zip)
  • v1.2.581(Feb 10, 2022)

    What's Changed

    • Fix phpstan errors by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/45
    • Update dev dependencies by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/46
    • Add issue/pull request templates by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/49
    • Switch to issue forms by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/50
    • Feat: Support PHP 7.2 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/48
    • Increase version before new release by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/51

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.2.481...v1.2.581

    Source code(tar.gz)
    Source code(zip)
  • v1.2.481(Jan 4, 2022)

    What's Changed

    • chore: update workflows after branch rename by @thomasheartman in https://github.com/Unleash/unleash-client-php/pull/39
    • Add possibility of changing sdk name and version for implementers by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/40

    New Contributors

    • @thomasheartman made their first contribution in https://github.com/Unleash/unleash-client-php/pull/39

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.2.381...v1.2.481

    Source code(tar.gz)
    Source code(zip)
  • v1.2.381(Dec 10, 2021)

    What's Changed

    • Migrate to PHP 8.1 as default version by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/33
    • Use newer phpstan and rector, use php 8.1 features by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/34
    • Add readonly to properties by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/36

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.2.280...v1.2.381

    Source code(tar.gz)
    Source code(zip)
  • v1.2.280(Oct 18, 2021)

    What's Changed

    • Fallback for cases when cache may return null by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/32

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.2.180...v1.2.280

    Source code(tar.gz)
    Source code(zip)
  • v1.2.180(Oct 15, 2021)

    What's Changed

    • Use php-http/discovery to find PSR-17/18 implementations by @Xenonym in https://github.com/Unleash/unleash-client-php/pull/27
    • Make it impossible to return null in getOrCreateBucket() by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/31

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.2.080...v1.2.180

    Source code(tar.gz)
    Source code(zip)
  • v1.2.080(Sep 10, 2021)

    What's Changed

    • Run tests on 8.1 by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/18
    • Use constant for hostname by @RikudouSage in https://github.com/Unleash/unleash-client-php/pull/26
    • Add environment property to context by @fenix20113 in https://github.com/Unleash/unleash-client-php/pull/25

    Full Changelog: https://github.com/Unleash/unleash-client-php/compare/v1.1.180...v1.2.080

    Source code(tar.gz)
    Source code(zip)
Owner
Unleash
The Open-Source Feature Toggle Service
Unleash
A Gitlab API wrapper that helps to automate common actions on CI jobs

Gitlab CI client This is a Gitlab API wrapper that helps to automate common actions on CI jobs (eg: Open a merge request, Open or close an issue etc)

SparkFabrik 2 May 2, 2022
A discord-feature rich API plugin for PMMP.

DiscordBot DiscordBot a core plugin that provides an extensive API for plugins to interact with a discord bot creating endless possibilities. Examples

null 2 Jan 9, 2022
It’s a bot using simple feature - jangan keseringan make (haram cok)

It’s a bot using simple feature - jangan keseringan make (haram cok)

null 2 Jan 26, 2022
It’s a bot using simple feature - jangan keseringan make (haram cok)

Indodax-machine It’s a bot using simple feature - jangan keseringan make (haram cok) Example of Request PHP (API-PANAS) Get Info Sample code below : <

null 2 Jan 26, 2022
PHP JSON-RPC 2.0 Server/Client Implementation with Automatic Client Class Generation via SMD

PHP JSON-RPC 2.0 Server/Client Implementation with Automatic Client Class Generation via SMD

Sergey Bykov 63 Feb 14, 2022
PHP Implementation of the all new Basecamp API

Basecamp SDK for PHP The Basecamp SDK for PHP enables PHP developers to easily integrate 37signals Basecamp all new API into their applications. NOTE:

Netvlies Internetdiensten 38 Feb 14, 2022
PHP library with ready-to-use Yunbi API implementation.

yunbi-client-php A simple PHP client for Crypto Trade Site Yunbi.com Quick example <?php require_once('lib/yunbi-client.php'); try { $client = new

null 6 Dec 2, 2019
Implementation of hopper logic for pushing, pulling and picking up items for PocketMine-MP.

VanillaHopper In pm4, hopper blocks were implemented to have an inventory. But the logic for pushing, pulling and picking up items was missing nonethe

Colin 14 Dec 14, 2022
The Kafka Enqueue transport - This is an implementation of Queue Interop specification

Supporting Enqueue Enqueue is an MIT-licensed open source project with its ongoing development made possible entirely by the support of community and

Enqueue 40 Oct 6, 2022
Implementation of a library to process SISP vinti4 payment in a easy way.

Implementation of a library to process SISP vinti4 payment in a easy way.

Faxi 6 Nov 3, 2022
⚡️ Web3 PHP is a supercharged PHP API client that allows you to interact with a generic Ethereum RPC.

Web3 PHP is a supercharged PHP API client that allows you to interact with a generic Ethereum RPC. This project is a work-in-progress. Code and docume

Web3 PHP 665 Dec 23, 2022
Lightweight PHP library for WhatsApp API to send the whatsapp messages in PHP provided by ultramsg.com

Ultramsg.com WhatsApp API PHP SDK Lightweight PHP library for WhatsApp API to send the whatsappp messages in PHP provided by Ultramsg.com Installation

Ultramsg 117 Dec 26, 2022
Google-api-php-client - A PHP client library for accessing Google APIs

Google APIs Client Library for PHP Reference Docs https://googleapis.github.io/google-api-php-client/main/ License Apache 2.0 The Google API Client Li

Google APIs 8.4k Dec 30, 2022
Wise-php - This library is written to accommodate the wise API's use in php projects With Wise

Wise-php - This library is written to accommodate the wise API's use in php projects With Wise you can automate payments, connect your business tools, and create ways to manage your finances. You can also power your cross-border and domestic payouts.

Albert Xhani 15 Nov 17, 2022
It's a PHP Application to simplify working with Google Sheets SDK for php.

About GoogleSheetsPHP It's a PHP Application to simplify working with Google Sheets SDK for php. Note: i used Slim 3 to construct the application but

Sami Alateya 5 Dec 20, 2022
Official repository of the AWS SDK for PHP (@awsforphp)

AWS SDK for PHP - Version 3 The AWS SDK for PHP makes it easy for developers to access Amazon Web Services in their PHP code, and build robust applica

Amazon Web Services 5.7k Jan 1, 2023
A framework agnostic PHP library to build chat bots

BotMan If you want to learn how to create reusable PHP packages yourself, take a look at my upcoming PHP Package Development video course. About BotMa

BotMan 5.8k Jan 3, 2023
PHP library for the Stripe API.

Stripe PHP bindings The Stripe PHP library provides convenient access to the Stripe API from applications written in the PHP language. It includes a p

Stripe 3.3k Jan 5, 2023
A simple PHP GitHub API client, Object Oriented, tested and documented.

PHP GitHub API A simple Object Oriented wrapper for GitHub API, written with PHP. Uses GitHub API v3 & supports GitHub API v4. The object API (v3) is

KNP Labs 2k Jan 7, 2023