定制 henzeb/laravel-pennant-gated 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

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

henzeb/laravel-pennant-gated

Composer 安装命令:

composer require henzeb/laravel-pennant-gated

包简介

A Pennant driver that gates per-scope features behind a global switch

README 文档

README

Build Status Latest Version on Packagist Total Downloads License

This package adds a gated driver for Laravel Pennant that wraps any other Pennant store and turns its global (unscoped) value into a switch that governs every scope at once, without ever touching their stored values.

Why

When you activate a Pennant feature for a scope, it becomes active for that scope immediately. There is no way to configure who a feature is intended for without also making it live for them right away, and no single switch that governs every scope a feature has ever been activated for:

Feature::for($betaUser)->activate('new-checkout');

Feature::for($betaUser)->active('new-checkout'); // true, live immediately

Pennant does provide Feature::deactivateForEveryone() to turn a feature off in a single call, but it does so by overwriting the stored value for every scope with false. The information about which scopes it was active for is gone. Turning the feature back on for the same scopes means activating each of them again.

The gated driver separates these two concerns. A scoped activation records who the feature is intended for, while the global (unscoped) value determines whether that targeting is currently in effect. A scoped check is only true when the feature is active both for that scope and globally:

// Configure who the feature is for. It is not active yet, because the
// global value has not been activated.
Feature::store('gated')->for($betaUser)->activate('new-checkout');
Feature::store('gated')->for($otherUser)->activate('new-checkout');

Feature::store('gated')->for($betaUser)->active('new-checkout'); // false

// Activate the feature globally. Every scope that was already configured
// becomes active immediately, without being activated individually.
Feature::store('gated')->activate('new-checkout');

Feature::store('gated')->for($betaUser)->active('new-checkout');  // true
Feature::store('gated')->for($otherUser)->active('new-checkout'); // true

// Deactivate the feature globally. The scoped configuration is left
// untouched.
Feature::store('gated')->deactivate('new-checkout');

Feature::store('gated')->for($betaUser)->active('new-checkout'); // false

// Activate it globally again. Both scopes are active again, with no
// further changes required.
Feature::store('gated')->activate('new-checkout');

Feature::store('gated')->for($betaUser)->active('new-checkout'); // true

Because the gated driver is a thin wrapper, it works with whichever store you already use for the feature's underlying values, such as database or array, or a custom driver of your own.

Installation

composer require henzeb/laravel-pennant-gated

Add a gated entry to the stores section of config/pennant.php, pointing store at whichever other store should be gated:

'stores' => [
    'gated' => [
        'driver' => 'gated',
        'store' => 'database',
    ],

    // Pennant's built-in stores, e.g.:
    'database' => [
        'driver' => 'database',
    ],
],

How it works

get($feature, $scope) on the underlying driver is checked twice:

get(feature, scope):
    if scope is null:
        return underlying->get(feature, null)   // the global value, unchanged

    if not underlying->get(feature, null):
        return false                            // global kill-switch is off

    return underlying->get(feature, scope)       // otherwise, defer to the scoped value

So:

  • Feature::active() (no scope) behaves exactly like the underlying driver.
  • Feature::for($user)->active() is true only when the feature is active both globally and for $user.

This applies to value() too, since it shares the same gating: if the feature carries a payload rather than a plain boolean, the scoped payload is only returned once the global gate is open.

Feature::store('gated')->activate('discount', ['percentage' => 10]);
Feature::store('gated')->for($user)->activate('discount', ['percentage' => 25]);

Feature::store('gated')->for($user)->value('discount'); // ['percentage' => 25]

Feature::store('gated')->deactivate('discount');
Feature::store('gated')->for($user)->value('discount'); // false, the gate is closed

Everything else — define, set, setForAllScopes, delete, purge, and, where supported by the underlying driver, definedFeaturesForScope, stored, setAll and flushCache — is delegated straight through to the underlying store.

Testing this package

composer test

Security

If you discover any security related issues, please email henzeberkheij@gmail.com instead of using the issue tracker.

Credits

License

The MIT License (MIT). Please see License File for more information.

统计信息

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

GitHub 信息

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

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-07-05

承接程序开发

PHP开发

VUE

Vue开发

前端开发

小程序开发

公众号开发

系统定制

数据库设计

云部署

网站建设

安全加固