antfroger/progressive 问题修复 & 功能扩展

解决BUG、新增功能、兼容多环境部署,快速响应你的开发需求

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

antfroger/progressive

Composer 安装命令:

composer require antfroger/progressive

包简介

The library to progressively, quickly and simply enables new features

README 文档

README

Progressive is a feature flag library (also called toggle, switch, ...).
Thanks to Progressive, you can progressively, quickly and simply enable new features. (and just as quickly deactivate them in case of an emergency)

Build Status Latest Stable Version

Installation

$ composer require antfroger/progressive

Usage

// From a file
$config = \Symfony\Component\Yaml\Yaml::parseFile('/your-own-config-file.yaml');
// Content of /your-own-config-file.yaml
// features:
//   dark-theme: true
//   call-center: false
//   homepage-v2:
//     enabled: true

// Or from a PHP array
$config = [
    'features' => [
        'dark-theme'  => true,
        'call-center' => false,
        'homepage-v2' => [
            'enabled' => true
        ],
    ]
];

$progressive = new Progressive($config);
$progressive->isEnabled('dark-theme');    // true
$progressive->isEnabled('call-center');   // false
$progressive->isEnabled('homepage-v2');   // true

Rules

Built-in

enabled: true|false

enabled enables (or disables) the feature for everyone, everywhere, all the time.
The value is meant to be a boolean, true|false.

// Short
$config = [
    'features' => [
        'dark-theme' => true
    ]
];

// Verbose
$config = [
    'features' => [
        'dark-theme'  => [
            'enabled' => true
        ]
    ]
];

Custom

You will probably need many more rules that will fit your needs and stack.

Let's say you want to redesign your homepage and progressively displaying it to test if everything goes right.
You start by enabling it in dev, then preprod, then prod but only for developers, then admins, then 1% of the users...
How would you be able to achieve that?

With custom rules!

$config = [
    'features' => [
        'homepage-v123'  => [
            'env' => ['DEV', 'PREPROD']
        ]
    ]
];
$progressive = new Progressive($config);

$progressive->addCustomRule('env', function (Context $context, array $envs) {
    return in_array(getenv('ENV'), $envs);
});

$progressive->isEnabled('homepage-v123'); // Returns true if ENV is DEV or PREPROD, otherwise returns false

(this lambda can be improved thanks to the Context object - more about it here)

Strategies

Rules are great but sometimes one rule is not enough to decide if a feature must be enabled.
You may want to enable a feature in PROD only for admins but to everyone in DEV, TEST and PREPROD.
Or you may want to enable a feature to the admins AND a given percentage of users.

That's where strategies come into play!

(Strategies are simply another name for nested rules.
And as for rules, you can create your own strategies!)

Progressive comes with two built-in strategies:

unanimous: []

unanimous enables the feature if all the conditions are met.
The value is meant to be an array of rules.

$config = [
    'features' => [
        'translate-interface'  => [
            'unanimous' => [
                'env'   => ['DEV', 'PREPROD'],
                'roles' => ['ROLE_ADMIN', 'ROLE_TRANSLATOR']
            ]
        ]
    ]
];

In this example, the interface to translate the app will only be displayed in DEV and PREPROD environments to users having ROLE_ADMIN or ROLE_TRANSLATOR as roles.
This strategy can be defined as an AND.

partial: []

partial enables the feature if only one of the conditions is met.
Rules are evaluated one by one. The feature is enabled as soon as one rule is true.
The value is meant to be an array of rules.

$config = [
    'features' => [
        'translate-interface'  => [
            'partial' => [
                'env'   => ['DEV', 'PREPROD'],
                'roles' => ['ROLE_ADMIN', 'ROLE_TRANSLATOR']
            ]
        ]
    ]
];

In this example, the interface to translate the app will be displayed:

  • in DEV and PREPROD environments (for all users)
  • for users having a role ROLE_ADMIN or ROLE_TRANSLATOR, regardless of the environment.

This strategy can be defined as an OR.

Context object

Progressive doesn't know anything of your application logic code (and doesn't want to know).
But you may want to use your logic inside custom rules.

In that case, the context object is your friend!
It's nothing more that an user-defined databag.

You can use it to improve our previous custom rule:

$context = new Context([
    'env' => getenv('ENV') ?: 'PROD'
]);

$config = [
    'features' => [
        'homepage-v123'  => [
            'env' => ['DEV', 'PREPROD']
        ]
    ]
];

$progressive = new Progressive($config, $context);
$progressive->addCustomRule('env', function (Context $context, array $envs) {
    return in_array($context->get('env'), $envs);
});

Another common example is to store the current user in the context:

$context = new Context(['user' => $user]);

$config = [
    'features' => [
        'homepage-v123'  => [
            'roles' => ['ROLE_ADMIN']
        ]
    ]
];

$progressive = new Progressive($config, $context);
$progressive->addCustomRule('roles', function (Context $context, array $roles) {
    $userRoles = $context->get('user')->getRoles();
    foreach ($roles as $role) {
        if (in_array($role, $userRoles) {
            return true;
        }
    }

    return false;
});

Requesting a non-existing flag

Whenever you request an non-existing flag, isEnabled will return false.
The flag is considered disabled.

$config = [
    'features' => []
];

$progressive = new Progressive($config);
$progressive->isEnabled('dark-theme'); // false

Separate feature releases from code deploy

As Progressive takes an array of config, it makes it possible to decorrelate the release calendar from the code deployment.
In this example, we use the Symfony Yaml component to read the config from a YAML file.

use Symfony\Component\Yaml\Yaml;

$config = Yaml::parseFile('/your-own-config-file.yaml');
// Content of /your-own-config-file.yaml
// features:
//   new-feature: false
$progressive = new Progressive($config);
$progressive->isEnabled('new-feature'); // false

Imagine that you are able to deploy the config files independently from your code base, you could release a new feature without having to deploy all your code base, by redeploying only /your-own-config-file.yaml.

// Content of /your-own-config-file.yaml
// features:
//   new-feature: true
$progressive->isEnabled('new-feature'); // true

You may also want to store the configuration in a database and pass it as an array to Progressive.

Progressive in your projects

Inspired by Laurent Callarec's javascript feature-flag library Banderole

antfroger/progressive 适用场景与选型建议

antfroger/progressive 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 3.14k 次下载、GitHub Stars 达 2, 最近一次更新时间为 2020 年 12 月 18 日, 在 PHP 生态内属于活跃度较高的组件。

我们在过去多个企业项目中使用过 antfroger/progressive 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 antfroger/progressive 我们能提供哪些服务?
定制开发 / 二次开发

基于 antfroger/progressive 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 3.14k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 2
  • 点击次数: 10
  • 依赖项目数: 1
  • 推荐数: 0

GitHub 信息

  • Stars: 2
  • Watchers: 1
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2020-12-18