phpfn/pipe

实现函数调用链的库

2.0.1 2020-11-22 21:17 UTC

This package is auto-updated.

Last update: 2024-09-23 05:51:13 UTC


README

基于RFC Pipe Operator的对象导向管道操作符实现。

安装

可以将此库安装到任何PHP应用程序中

$ composer require phpfn/pipe

为了访问库,请确保在您的文件中包含 vendor/autoload.php

<?php

require __DIR__ . '/vendor/autoload.php';

使用方法

PHP OOP的一种常见模式是使用方法链,也称为“流畅表达式”。这个名称来源于一个方法如何流到下一个方法,形成一个概念上的超表达式。

然而,当使用函数式方法时,这可能会导致可读性降低、符号表污染或类型不一致,例如以下示例

<?php

$snakeCase = strtolower(
    preg_replace('/(.)(?=[A-Z])/u', '$1_', 
        preg_replace('/\s+/u', '', 
            ucwords('HelloWorld')
        )
    )
);
             
var_dump($snakeCase); // "hello_world"

管道库修复了这个问题,允许你链式执行纯函数

pipe('Hello World')
    ->ucwords(_)
    ->preg_replace('/\s+/u', '', _)
    ->preg_replace('/(.)(?=[A-Z])/u', '$1_', _)
    ->strtolower(_)
    ->var_dump;
//
// string(11) "hello_world"
//

另一个示例

见:https://wiki.php.net/rfc/pipe-operator#file_collection_example

<?php
$result = array_merge(
    $result,
    namespaced\func\get_file_arg(
        array_map(
            function ($x) use ($arg) {
                return $arg . '/' . $x;
            },
            array_filter(
                scandir($arg),
                function ($x) {
                    return $x !== '.' && $x !== '..';
                }
            )
        )
    )
);

使用此库,上述内容可以轻松重写为

<?php

$result = pipe($arg)
    ->scanDir($arg)
    ->array_filter(_, fn($x): bool => $x !== '.' && $x !== '..')
    ->array_map(fn($x): string => $arg . '/' . $x, _)
    ->use('namespaced\func')->get_file_arg
    ->array_merge($result, _);

处理值

要将值作为参数传递给函数,请使用下划线 (_) 字符

<?php

pipe('hello')
    ->str_replace('o', '', _)
    ->var_dump; // "hell"

如果只使用一个参数,则可以省略括号

<?php

pipe('some')
    ->is_array
    ->var_dump; // bool(false) 

要获取值,请使用以下选项之一

<?php
$context = pipe('hello')->strtoupper;

var_dump($context);
// object(Fun\Pipe\Pipe)#8 (1) { ... } 

var_dump($context());
// string(5) "HELLO"

处理命名空间

让我们用一个简单的例子来说明这种代码

namespace {
    function foo() { return __FUNCTION__; }
}

namespace Example {
    function foo() { return __FUNCTION__; }
}

让我们尝试管理命名空间

$context = pipe()->use('Example')->foo;

echo $context(); // 'Example\\foo'

$context = $context->foo;

echo $context(); // 'foo'

请注意,use 函数仅应用于后续函数,所有当前上下文中执行的操作

pipe()
    ->use('Some\\Namespace')->foo // Call "\Some\Namespace\foo()"
    ->foo // Call "\foo()"
;

为了在另一个命名空间中执行多个操作,请将匿名函数作为第二个 use 参数。

pipe()
    ->use('Some\\Namespace', fn($pipe) => 
        $pipe
            ->a // Call "\Some\Namespace\a()"
            ->b // Call "\Some\Namespace\b()"
    )
    ->a // Call "a()"
;

请注意,->use() 方法的行为取决于是否传递了第二个参数。