chefhasteeth/pipeline

v1.0.4 2024-06-02 15:06 UTC

This package is auto-updated.

Last update: 2024-09-02 15:41:54 UTC


README

Example code showcasing the Pipeline package using the with transaction method and the pipable trait

安装

通过composer安装

composer require chefhasteeth/pipeline

管道有哪些用途?

管道允许您通过一系列管道传递数据以执行一系列操作。每个管道都是一个可调用的代码片段:一个可调用的类、一个闭包等。由于每个管道独立地对数据进行操作(管道不知道或不在乎彼此),这意味着您可以轻松地组合复杂的流程,这些流程也是可重用的操作,并且非常容易测试——因为它们是相互独立的。

是什么让它变得如此强大?

如果Laravel是一个“内置电池”的PHP框架,那么这个包可以被认为是Illuminate\Pipeline\Pipeline类的“内置电池”版本。它与Laravel的管道保持(主要是)兼容,但也有一些差异和新增功能。

例如,您注意到上面的withTransaction()方法吗?这将告诉管道我们希望在数据库事务中运行这个操作,它将自动提交或回滚,具体取决于管道是否成功或失败。它还附带一个特性,提供了一个pipeThrough()方法,可以自动将实现它的对象通过管道传递。

有哪些差异?

在Laravel的Pipeline类中,管道本质上是接收两个参数的可调用对象:$passable,这是传递给管道的数据,以及一个$next回调,它调用下一个管道。

为了使我的管道可以从任何地方轻松使用,而不仅仅是管道中。例如,这可以是一个出现在管道中的GenerateThumbnail动作,但也可能出现在cron作业中。换句话说,我不想为了满足那个$next参数而向类或函数传递一个空的闭包。

这是这个包与Laravel的Pipeline之间最大的区别:当前管道的输出是下一个管道的输入。

将管道发送到管道中

在配置管道时,您可以将类字符串数组、可调用的对象、闭包、具有handle()方法的对象或任何其他通过is_callable()的类型发送到管道。

use Chefhasteeth\Pipeline\Pipeline;

class RegisterController
{
    public function store(StoreRegistrationRequest $request)
    {
        return Pipeline::make()
            ->send($request->all())
            ->through([
                RegisterUser::class,
                AddMemberToTeam::class,
                SendWelcomeEmail::class,
            ])
            ->then(fn ($data) => UserResource::make($data));
    }
}

另一种方法是在数据对象上实现这个特性。(如果您真的想的话,甚至可以在您的FormRequest对象上实现。)

use Chefhasteeth\Pipeline\Pipable;

class UserDataObject
{
    use Pipable;

    public string $name;
    public string $email;
    public string $password;
    // ...
}

class RegisterController
{
    public function store(StoreRegistrationRequest $request)
    {
        return UserDataObject::fromRequest($request)
            ->pipeThrough([
                RegisterUser::class,
                AddMemberToTeam::class,
                SendWelcomeEmail::class,
            ])
            ->then(fn ($data) => UserResource::make($data));
    }
}

为了与Laravel的Pipeline类保持兼容,through()方法可以接受一个可调用对象的单个数组或多个参数,其中每个参数都是之前列出的可调用类型之一。然而,pipeThrough()特性方法只接受一个数组,因为它还有一个可选的第二个参数。

使用数据库事务

当您想在管道中使用数据库事务时,方法将根据您是使用特性还是Pipeline类而有所不同。

使用Pipeline

Pipeline::make()->withTransaction()

withTransaction() 方法会告诉管道使用事务。当您调用 then()thenReturn() 方法时,在执行管道之前会开始数据库事务。如果在管道中遇到异常,事务将被回滚,因此不会将任何数据提交到数据库。假设管道成功完成,则事务将被提交。

当使用该特质时,您可以向 pipeThrough() 方法传递第二个参数。

$object->pipeThrough($pipes, withTransaction: true);

测试

composer test

许可证

MIT 许可证 (MIT)。有关更多信息,请参阅 LICENSE