setherator/variables

Setherator 变量管理库。使用一些额外的魔法管理和处理变量值。

1.0.3 2020-04-23 12:06 UTC

This package is auto-updated.

Last update: 2024-09-23 22:33:37 UTC


README

Latest Version on Packagist Software License Build Status Code Quality Code Coverage Mutation testing badge Total Downloads

Email

Setherator 变量管理库。使用一些额外的魔法管理和处理变量值。

安装

通过 Composer

$ composer require setherator/variables

用法

《Variables》及其辅助函数的几个用例的汇编。

use Setherator\Variables\Variables;
use function Setherator\Variables\all;
use function Setherator\Variables\context;
use function Setherator\Variables\factory;
use function Setherator\Variables\logic;
use function Setherator\Variables\passthrough;
use function Setherator\Variables\ref;

$variables = new Variables();
$variables->setContext(['Prefix: ']);

$globalLogicState  = true;
$providedVariables = [
    'scalar'              => 'foo',
    // will execute closure and catch value
    'closure'             => fn() => 'closure Foo ' . random_int(1, 10),
    // Will be fetched at code load
    'ref'                 => ref('scalar', 'Not found'),
    // Will be only fetched when 'ref_on_get' is fetched
    'ref_on_get'          => fn() => ref('scalar'),
    // will return number increasing every time its fetched and 'Number: ' will be passed as argument to
    'factory'             => factory(
        function ($prefix) {
            static $i = 0;

            return $prefix . $i++;
        },
        function () {
            static $i = 0;

            return 'Number ' . $i++ . ': ';
        },
    ),
    // Will inject context values as arguments from Variables::getContext();
    'context'             => context(fn(string $prefix) => $prefix . random_int(1, 10)),
    'factory_context'     => factory(context(fn(string $prefix) => $prefix . random_int(1, 10))),
    'all'                 => all(
        fn() => 'First',
        fn() => 'Second',
        'Third'
    ),
    'logic'               => logic(
        fn() => 1,
        fn() => 'Condition: true',
        fn() => 'Condition: false',
    ),
    'logic_strict'        => logic(
        fn() => 1,
        fn() => 'Condition: true',
        fn() => 'Condition: false',
        true
    ),
    'logic_factory'       => factory(
        logic(
            function () use (&$globalLogicState) {
                return $globalLogicState;
            },
            function () use (&$globalLogicState) {
                $globalLogicState = !$globalLogicState;

                return 'Factory Condition: true';
            },
            function () use (&$globalLogicState) {
                $globalLogicState = !$globalLogicState;

                return 'Factory Condition: false';
            },
        )
    ),
    'passthrough'         => passthrough(
        Closure::fromCallable('strtoupper'),
        fn() => 'Passthrough: ' . ref('logic_factory'),
    ),
    'passthrough_factory' => factory(
        passthrough(
            Closure::fromCallable('strtoupper'),
            fn() => 'Passthrough Factory: ' . ref('logic_factory'),
        )
    ),
    'first' => first(
        0,
        'value'
    ),
];


$variables->add($providedVariables);


echo $variables->get('scalar') . PHP_EOL;
echo $variables->get('closure') . PHP_EOL;
echo $variables->get('closure') . PHP_EOL;
echo $variables->get('ref') . PHP_EOL;
echo $variables->get('ref_on_get') . PHP_EOL;
echo $variables->get('factory') . PHP_EOL;
echo $variables->get('factory') . PHP_EOL;
echo $variables->get('context') . PHP_EOL;
echo $variables->get('context') . PHP_EOL;
echo $variables->get('factory_context') . PHP_EOL;
echo $variables->get('factory_context') . PHP_EOL;
echo json_encode($variables->get('all')) . PHP_EOL;
echo $variables->get('logic') . PHP_EOL;
echo $variables->get('logic_strict') . PHP_EOL;
echo $variables->get('logic_factory') . PHP_EOL;
echo $variables->get('logic_factory') . PHP_EOL;
echo $variables->get('logic_factory') . PHP_EOL;
echo $variables->get('passthrough') . PHP_EOL;
echo $variables->get('passthrough') . PHP_EOL;
echo $variables->get('passthrough_factory') . PHP_EOL;
echo $variables->get('passthrough_factory') . PHP_EOL;
echo $variables->get('passthrough_factory') . PHP_EOL;
echo $variables->get('first') . PHP_EOL . PHP_EOL;

// Print all computed values
echo json_encode($variables->all(), JSON_PRETTY_PRINT) . PHP_EOL;

// Print all non computed values (Closures do not json encode)
echo json_encode($variables->all(false), JSON_PRETTY_PRINT) . PHP_EOL;

将得到


foo
closure Foo 4
closure Foo 4
Not found
foo
Number 0: 0
Number 1: 1
Prefix: 6
Prefix: 6
Prefix: 10
Prefix: 1
["First","Second","Third"]
Condition: true
Condition: false
Factory Condition: true
Factory Condition: false
Factory Condition: true
PASSTHROUGH: FACTORY CONDITION: FALSE
PASSTHROUGH: FACTORY CONDITION: FALSE
PASSTHROUGH FACTORY: FACTORY CONDITION: TRUE
PASSTHROUGH FACTORY: FACTORY CONDITION: FALSE
PASSTHROUGH FACTORY: FACTORY CONDITION: TRUE
value

{
    "scalar": "foo",
    "closure": "closure Foo 4",
    "ref": "Not found",
    "ref_on_get": "foo",
    "factory": "Number 2: 2",
    "context": "Prefix: 6",
    "factory_context": "Prefix: 8",
    "all": [
        "First",
        "Second",
        "Third"
    ],
    "logic": "Condition: true",
    "logic_strict": "Condition: false",
    "logic_factory": "Factory Condition: false",
    "passthrough": "PASSTHROUGH: FACTORY CONDITION: FALSE",
    "passthrough_factory": "PASSTHROUGH FACTORY: FACTORY CONDITION: TRUE",
    "first": "value"
}

{
    "scalar": "foo",
    "closure": "closure Foo 4",
    "ref": "Not found",
    "ref_on_get": "foo",
    "factory": {},
    "context": "Prefix: 6",
    "factory_context": {},
    "all": [
        "First",
        "Second",
        "Third"
    ],
    "logic": "Condition: true",
    "logic_strict": "Condition: false",
    "logic_factory": {},
    "passthrough": "PASSTHROUGH: FACTORY CONDITION: FALSE",
    "passthrough_factory": {},.
    "first": {}
}

辅助函数

变量值可以是任何标量、数组、对象类型,也可以是闭包,该闭包将被执行并缓存。要防止缓存,应实现 NonCacheableClosure 接口,例如 factory 辅助函数。

参考

一个从 Variables 实例获取变量值的函数。如果未找到,将返回 $default = null。如果需要评估前的原始值,请使用 $raw = true

function ref(string $name, $default = null, bool $raw = false);
function reference(string $name, $default = null, bool $raw = false);

要获取变量获取时的值,请使用这些函数。

function refFn(string $name, $default = null, bool $raw = false);
function referenceFn(string $name, $default = null, bool $raw = false);

环境变量

一个用于获取环境变量的函数。如果未找到,将返回 $default = null

function env(string $name, $default = null): string;

上下文

一个用于包装您的闭包并从 Variables::getContext() 注入上下文的函数;

function context(Closure $closure, ...$args): Closure;Cacheable

将返回一个包装了上下文变量 + 额外的 $args 作为参数的闭包。 $args 将使用 Variables::parseValue() 函数进行评估。它将表现得像正常的 Variable 值。

[
    'context_aware_variable' => context(
        function (Setherator $setherator, string $input) {
            // ... Your logic
            
            return 'Your typed input: ' . $input;
        },
        ask('Input')
    ),
]

注意:返回的上下文闭包不接受任何参数。

工厂

一个用于防止您的闭包值被缓存的函数。每次访问值时都会调用您的闭包。 $args 将作为参数传递给闭包函数。 $args 将使用 Variables::parseValue() 函数进行评估。它将表现得像正常的 Variable 值。

function factory(Closure $closure, ...$args): NonCacheableClosure;

将返回一个实现 NonCacheableClosure 接口并防止其缓存的值,表现得像您的正常闭包。

[
    'factory_value' => factory(
        function (string $input) {
            // ... Your logic
            
            return 'Your typed input: ' . $input;
        },
        ask('Input')
    ),
]

所有

一个评估传递给参数的所有值并返回结果作为数组的函数。

function all(...$args): array

将返回一个包含所有已评估 $args 的数组。

[
    'all' => all(
        ask('Please provide project name'),
        ask('Please provide folder name')
    )
]

提示:要评估变量获取时的所有值,请使用函数: allFn(/* ... */)

逻辑

一个评估条件并决定使用哪个值的函数。 $condition$true$false 使用 Variables::parseValue() 函数进行评估。

function logic($condition, $true, $false, bool $strict = false): Closure;

将返回一个闭包,该闭包将根据 $condition 决定返回 $true$false

[
    'logic_based_value' => logic(
        fn() => askChoice('Please select app env', ['dev', 'prod']) !== 'dev',
        'Environement is production',
        fn() => 'Enviroment is dev and time is: ' . time()
    )
]

注意:逻辑返回的闭包不接受任何参数。

透传

一个将所有评估后的值作为参数传递给闭包的函数。

function passthrough(Closure $closure, ...$args): Closure;

将返回一个将评估后的 $args 作为参数传递给闭包的闭包。

[
    'passthough_value' => passthrough(
        function (string $projectName, string $projectFolderName) {
            return 'Project "' . $projectName . '" at "' . $projectFolderName . '"';
        }
        ask('Please provide project name'),
        ask('Please provide project folder name')
    )
]

注意:透传返回的闭包不接受任何参数。

第一个

一个从参数返回第一个真值的函数。 $args 将使用 Variables::parseValue() 函数进行评估。

function first(...$args);

提示:要评估变量获取时的值,请使用函数: firstFn(/* ... */)

值解析器

您可以为访问变量值时进行解析而实现自己的值解析器。

class JsonEncodeValue
{
    private $value;
    
    public function __construct($value)
    {
        $this->value = $value;
    }
    
    public function getValue()
    {
        return $this->value;
    }
}

class JsonEncodeValueParser implements ValueParserInterface
{
    public function supports($value): bool
    {
        return $value instanceof JsonEncodeValue;
    }

    public function parseValue($value, Variables $variables)
    {
        return json_encode($value->getValue());
    }
}

$variables = new Variables();
$variables->addValueParser(new JsonEncodeValueParser());

$variables->set('json', new JsonEncodeValue(['foo' => 'bar']);
$variables->get('json') // => {"foo":"bar"}

测试

运行测试用例

$ composer test

以 HTML 格式运行测试用例覆盖率

$ composer test-coverage

运行 PHP 风格检查器

$ composer cs-check

运行 PHP 风格修复器

$ composer cs-fix

运行所有持续集成测试

$ composer ci-run

贡献

有关详细信息,请参阅 CONTRIBUTINGCONDUCT

许可证

有关更多信息,请参阅 许可证文件