defstudio / actions
Laravel Actions 的辅助方法
Requires
- php: ^8.0
- illuminate/contracts: ^8.37|^9.0|^10.0
- spatie/laravel-package-tools: ^1.9.2
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.2.1
- nunomaduro/collision: ^5.10 || ^v6.1.0
- nunomaduro/larastan: ^1.0
- orchestra/testbench: ^6.22|^7.0|^8.0
- pestphp/pest: ^1.10
- pestphp/pest-plugin-laravel: ^1.1
- pestphp/pest-plugin-mock: ^1.0
- phpstan/extension-installer: ^1.1
- phpstan/phpstan-deprecation-rules: ^1.0
- phpstan/phpstan-phpunit: ^1.0
- phpunit/phpunit: ^9.4
- spatie/laravel-ray: ^1.26
README
创建 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 Leiva 的 Laravel Actions 启发,并作为有见地和简化的实现而构建。如果您需要更强大的工具,应该查看它。
许可证
MIT 许可证 (MIT)。有关更多信息,请参阅 许可证文件