defstudio/actions

Laravel Actions 的辅助方法

v1.1.4 2024-05-21 08:12 UTC

README

Latest Version on Packagist GitHub Tests Action Status GitHub Code Style Action Status GitHub Static Analysis Action Status Total Downloads

创建 Action 类的轻量级包

安装

您可以通过 composer 安装此包

composer require defstudio/actions

用法

use DefStudio\Actions\ActAsAction; 特性添加到您的动作类中,或扩展 DefStudio\Actions\Action

(可选) 添加一个 dockblock 来提示静态 run 方法的参数和返回类型

/**
 * @method static void run(Report|int $report)
 */
class DeleteReport
{
    use ActsAsAction;

    public function handle(Report|int $report): void
    {
        if (is_int($report)) {
            $report = Report::findOrFail($report);
        }

        DB::transaction(function () use ($report) {
            $report->delete_data();
            $report->delete();
        });
    }
}

class DeleteReport extends \DefStudio\Actions\Action
{
    public function handle(Report|int $report): bool
    {
        if (is_int($report)) {
            $report = Report::findOrFail($report);
        }

        return DB::transaction(function () use ($report) {
            $report->delete_data();
            return $report->delete();
        });
    }
}

使用新方法

$result = DeleteReport::run($report->id); //true

$result = DeleteReport::make()->handle($report->id); //true

一次性运行多个动作

一个动作可以通过调用其 runMany() 方法多次运行

$results = DeleteReport::runMany($report1->id, $report2->id, $report3->id); //[true, false, true]

每次运行的输出将收集到一个数组中,并通过 runMany() 返回

备注

如果需要多个参数,它们可以包装在数组中(关联数组的键将被视为命名参数)

class{
    use InjectsItself;
 
    public function handle($name = 'guest', $title = 'Mr.'): string
    {
        return "$title $name";
    }
}

$result = MyAwesomeAction::runMany(['Elizabeth', "Ms."], ['Fabio'],  ['title' => 'Mrs.']);

// $result = ["Ms. Elizabeth", "Mr. Fabio", "Mrs. guest"] 

可模拟的动作

您还可以为动作定义一个模拟(它将自动绑定到应用容器)

FindTheAnswerToLifeTheUniverseAndEverything::mock(fn ($report_id) => 42);

FindTheAnswerToLifeTheUniverseAndEverything::run() // 42

如果您只对模拟返回值感兴趣,可以编写

FindTheAnswerToLifeTheUniverseAndEverything::mock(42);

如果您的动作有除 handle 之外的公共方法,它们也可以被模拟

MyWeirdAction::mock(handle: fn() => 5, handleForAdmin: fn() => 42);

无参数时,mocks 返回一个准备使用的 MockInterface 实例

MyAction::mock()->shouldNotReceive('handle');

部分模拟(例如,对于具有多个方法的动作)

BuildOrder::partial_mock(fromRequest: fn() => true);

//this will not be mocked
BuildOrder::make()->fromJson($data);

除了模拟,动作还可以被 spied

$spiedAction = MyAction::spy();

$spiedAction->handle();
$spiedAction->handle();

$spiedAction->shouldHaveReceived()->handle()->twice()

可调度动作

一个动作可以通过使用 ActsAsJob 特性(或扩展 Action 类)作为作业进行 dispatchable

可以通过调用 job() 静态方法创建作业

dispatch(LongRunningAction::job($argument_1, $argument_2));

或使用其专用方法调度

LongRunningAction::dispatch($argument_1, $argument_2);

LongRunningAction::dispatchSync($argument_1, $argument_2);

LongRunningAction::dispatchAfterResponse($argument_1, $argument_2);

动作将包装在 ActionJob 装饰器中,并按需代理属性

use DefStudio\Actions\Concerns\ActsAsJob;

class LongRunningAction{
    use ActsAsJob;
    
    public int $timeout = 2 * 60 * 60;
    public int $tries = 4;
    public array $backoff = [60, 120, 300, 600];
    public string $queue = 'long-running';
    
    public function handle(){...}
}

清理失败的动作作业

可以通过定义 jobFailed() 方法来处理失败的动作作业

class LongRunningAction{
    use ActsAsJob;
       
    public function handle(){..}
    
    public function jobFailed($exception)
    {
        $this->handleFailure();
    }
    
    private function handleFailure(){..}
}

动作作业的批量和链

类似于 runMany() 方法,可以从参数数组创建新的批量和链动作作业

MyAction::batch([$name1, $title1], [$name2, $title2])->dispatch();

MyAction::chain([$name1, $title1], [$name2, $title2])->dispatch();

测试

composer test

变更日志

有关最近更改的更多信息,请参阅 CHANGELOG

贡献

有关详细信息,请参阅 CONTRIBUTING

安全漏洞

有关如何报告安全漏洞的更多信息,请参阅 我们的安全策略

鸣谢

该项目受 Loris LeivaLaravel Actions 启发,并作为有见地和简化的实现而构建。如果您需要更强大的工具,应该查看它。

许可证

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