youcanshop / foggle
Laravel的功能标志包。
Requires
- php: >=7.4
- azuradara/illumake: ^1.0
Requires (Dev)
- laravel/framework: >=5.8
- orchestra/testbench: ^6.0|^8.0
- pestphp/pest: ^1
- phpstan/phpstan: ^1.10
- rector/rector: ^0.18.3
README
一个为Laravel构建的,以用户体验为中心的功能标志包。
注意
某些功能尚未实现
- 功能解析清除命令。
- 全局标志的预解析钩子。
安装
使用Composer将Foggle安装到您的项目中
composer require youcan-shop/foggle
然后,您应该使用以下Artisan命令发布配置文件
php artisan vendor:publish --provider="YouCanShop\Foggle\FoggleServiceProvider"
配置
发布后,配置文件将位于config/foggle.php。这是您配置存储提供者和上下文解析器的地方。Foggle允许您将功能标志的解析存储在大量数据存储中,或者在内存中的array驱动中。
功能定义
要定义功能,您可以使用foggle()辅助函数的define方法。您需要提供一个功能的名称以及一个解析初始值的闭包。
通常,功能应该在专用的服务提供器中定义。闭包将接收解析的上下文作为参数,这通常是您的应用程序的User模型。
<?php namespace App\Providers; use App\Models\User; use Illuminate\Support\ServiceProvider; class AppServiceProvider extends ServiceProvider { public function boot(): void { foggle()->define('themes', fn (User $user) => match (true) { $user->isTeamMember() => true, $user->isTestUser() => false, default => false, }); } }
对于给定上下文(用户)的第一次themes功能解析,结果将由您的配置驱动存储。下次它对该上下文进行检查时,闭包将不会调用,值将从存储中检索。
基于类的功能与发现
Foggle允许您定义基于类的功能。这些类可以自动发现并注册到功能管理器中。默认情况下,自动发现路径为app/Features,但可以从配置文件中更改。
编写功能类时,您需要定义一个resolve或__invoke方法,该方法将被调用来解析功能的初始值。在这种情况下,类的FQN将被用作功能名称,但您可以通过在功能类上定义公共name方法来覆盖它。
<?php namespace App\Features; use App\Models\User; use Illuminate\Support\Lottery; class NewApi { public function resolve(User $user): mixed { return match (true) { $user->isInternalTeamMember() => true, $user->isHighTrafficCustomer() => false, default => Lottery::odds(1 / 100), }; } }
检查功能
要评估功能值,您可以使用foggle()辅助函数上的active方法。
<?php function are_themes_active() { return foggle()->active('themes'); }
如果您需要针对特定上下文检查功能,可以在功能解析调用之前使用for方法,如下所示
<?php function are_themes_inactive(User $user) { return foggle()->for($user)->inactive('themes'); }
内存缓存
当解析功能时,Foggle将在内存中创建结果缓存。例如,如果您使用的是redis驱动程序,这意味着在单个请求的生命周期内重新检查同一功能将不会触发额外的Redis查询。
如果您需要手动清除内存缓存,可以使用cFlush方法在foggle()辅助函数上。请注意,在控制台运行时,每次处理作业都会清除内存缓存,以确保长时间运行的工人进程始终具有最新值。
foggle()->cFlush()
上下文
解析器
如前所述,Foggle允许您使用foggle()上的for方法针对任何上下文检查功能。但是,如果您希望在每次检查功能时都省略for,您可以在配置文件中配置自定义上下文解析器。
您可以通过创建一个实现ContextResolver的类来做到这一点
<?php namespace App\ContextResolvers; use App\Services\StoreService; use YouCanShop\Foggle\Contracts\ContextResolver; class StoreResolver implements ContextResolver { public function __construct(private readonly StoreService $storeService) { } public function resolve(): ?Store { return $this->storeService->getCurrentStore(); } }
然后您应该将此类绑定到它解析的上下文类型,在本例中是配置文件中的 Store 类型。
<?php return [ // ... 'context_resolvers' => [ Store::class => StoreResolver::class, ] ];
定义功能上下文类型
默认情况下,如果您没有为功能提供上下文,它将不会尝试使用上下文解析器,并默认为 null。您可以在功能定义中通过两种方式之一告诉 Foggle 使用哪个解析器:
- 当使用基于类的功能时,您必须在类中定义一个公共的
$contextType属性,包含上下文的类名。 - 当使用基于闭包的功能或
FogGen生成时,您可以将上下文类型声明为foggle()方法上的define方法的第三个参数。
上下文标识符
Foggle 的内置驱动程序将存储您的上下文及其解析值在其存储中。但是,将某些上下文序列化为原始形式可能会对某些数据存储(例如 Redis)产生较大负担,因此每个不是字符串的上下文都必须实现 Foggable 接口。
<?php namespace App\Models; use FlagRocket\FlagRocketUser; use Illuminate\Database\Eloquent\Model; use YouCanShop\Foggle\Contracts\Foggable; class User extends Model implements Foggable { public function foggleId(): string { return $this->id; } }
功能生成
一些功能可能过于简单,不值得为每个定义创建一个完整的类或重复使用闭包,这就是为什么 Foggle 提供了一个 FogGen 类,用于生成常见的功能闭包。
FogGen::inconfig()
该 inconfig 方法接收一个配置路径,并生成一个检查给定上下文标识符是否包含在提供的配置值中的功能。如果配置值是一个字符串,inconfig 将默认使用逗号(,)分隔符将其拆分成数组,这可以通过其可选的第二个参数进行更改。
<?php foggle()->define('billing-v2', FogGen::inconfig('features.billing-v2.stores', ','), Store::class);
在这种情况下,它将检查存储的 id 属性是否存在于 features.billing-v2.stores 值中。