serafim/pipe

此包已被废弃,不再维护。作者建议使用https://github.com/phpfn/pipe包。

实现函数调用链的库

2.0.1 2020-11-22 21:17 UTC

This package is auto-updated.

Last update: 2020-11-22 21:18:21 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()方法的操作行为取决于是否传递了第二个参数。