zachflower / eloquent-interactions
Laravel 的交互模式实现。
Requires
- php: ^7.2.5|^8.0
- illuminate/console: ^7.0|^8.0|^9.0|^10.0
- illuminate/support: ^7.0|^8.0|^9.0|^10.0
- illuminate/validation: ^7.0|^8.0|^9.0|^10.0
Requires (Dev)
- dms/phpunit-arraysubset-asserts: ^0.5.0
- mockery/mockery: ^1.0
- orchestra/testbench: ^5.0|^6.0|^7.0|^8.0
- phpunit/phpunit: ^8.0|^9.0
README
Eloquent Interactions 管理应用特定的业务逻辑。它是在 PHP for Laravel 中的命令模式实现,灵感来源于 Ruby 中的 ActiveInteraction 库。
Eloquent Interactions 为您提供了一个放置业务逻辑的地方。它还通过验证您的输入是否符合预期来帮助您编写更安全的代码,并提供了创建离散、易于测试的代码的平台。
安装
要安装 Eloquent Interactions,请通过 Composer 需求库。
composer require zachflower/eloquent-interactions
Eloquent Interactions 考虑到 Laravel 7.0+ 进行构建,目前测试正在验证与 Laravel 7、8、9 和 10 的兼容性,PHP 版本从 7.2.5 到 8.3。如果您发现与您特定的 Laravel 或 PHP 版本有任何问题,请 创建问题,我会尽力解决。
基本使用
要开始使用 Eloquent Interactions,首先创建一个新的交互。交互通常位于 app/Interactions
目录中,但您可以根据您的 composer.json
文件将其放置在可以自动加载的任何位置。所有 Eloquent Interactions 都扩展了 \ZachFlower\EloquentInteractions\Interaction
抽象类。
创建交互的最简单方法是使用 make:interaction
Artisan 命令。
php artisan make:interaction ConvertMetersToMiles
现在,让我们看一下上面 make:interaction
命令创建的基交互
<?php namespace App\Interactions; use ZachFlower\EloquentInteractions\Interaction; class ConvertMetersToMiles extends Interaction { /** * Parameter validations * * @var array */ public $validations = [ // ]; /** * Execute the interaction * * @return void */ public function execute() { // } }
一旦生成,每个交互都需要以下两个组件
- 输入验证。类
$validations
属性使用内置的 Laravel 验证器 定义和验证给定交互的预期输入。或者,可以用validations()
方法替换$validations
属性。 - 业务逻辑。
execute()
方法接收提供输入(当然是在通过验证之后)并在其上执行必要的业务逻辑。您定义的每个输入都将可用。如果有任何输入无效,则不会运行execute()
。
有了这些信息,让我们更新生成的交互以使其可用
<?php namespace App\Interactions; use ZachFlower\EloquentInteractions\Interaction; class ConvertMetersToMiles extends Interaction { /** * Parameter validations * * @var array */ public $validations = [ 'meters' => 'required|numeric|min:0', ]; /** * Execute the interaction * * @return void */ public function execute() { return $this->meters * 0.000621371; } }
要执行交互,您可以在类上调用静态 run()
方法。由于交互的 $validations
属性定义了预期的输入,应将简单的键值数组传递给 run()
,其中包含预期的输入。此方法将返回一个 \ZachFlower\EloquentInteractions\Outcome
类的新实例。要检查结果的成功,Outcome
对象上的 $valid
属性将被设置为布尔值,其中 TRUE
表示输入验证通过,而 FALSE
表示失败。如果验证失败,所有验证错误都将存储在 Outcome
对象上的 $errors
属性中。如果验证通过,则 execute()
方法返回的值将存储在 Outcome
对象上的 $result
属性中。
>>> $outcome = ConvertMetersToMiles::run(['meters' => 100]); >>> $outcome->valid; => true >>> $outcome->result; => 0.0621371 >>> $outcome = ConvertMetersToMiles::run(['meters' => 'one hundred']); >>> $outcome->valid; => false >>> $outcome->errors->toArray() => [ "meters" => [ "The meters field must be a number.", ], ]
如果您希望自行处理错误处理,可以在run()
方法的第二个参数中传递TRUE
。这,姑且这么说,将以“危险”的方式执行交互,意味着任何定义的错误都将被抛出为类型为\ZachFlower\EloquentInteractions\Exceptions\ValidationException
的异常。
>>> $outcome = App\Interactions\Utility\ConvertMetersToMiles::run(['meters' => 'one hundred'], TRUE); Illuminate\Validation\ValidationException with message 'The given data failed to pass validation.' >>> $outcome->errors->toArray(); => [ "meters" => [ "The meters field must be a number.", ], ]
验证
Eloquent Interactions高度依赖于内置的Laravel验证器。这意味着在Laravel应用程序中可用的任何验证方法也将可用于Eloquent Interactions验证器。话虽如此,目前有一个自定义验证器(更多即将推出),以更好地支持Eloquent Interactions的后端特性。
高级验证器
如果内置的验证器无法满足您的需求,您可以使用validations()
方法代替$validations
属性。例如,假设我们想在上面的示例中使用一个类来验证meters
参数。我们的交互将更改为如下所示
<?php namespace App\Interactions; use ZachFlower\EloquentInteractions\Interaction; class ConvertMetersToMiles extends Interaction { /** * Execute the interaction * * @return void */ public function execute() { return $this->meters * 0.000621371; } /** * Parameter validations * * @var array */ public function validations() { return [ 'meters' => ['required', new MyMetersRule()], ]; } }
对象
在某些情况下,可能需要验证对象的类型。例如,如果我们想验证输入参数是User
模型,可以使用以下验证规则
public $validations = [ 'user' => 'required|object:App\Models\User' ];
总的来说,这个验证器检查输入参数的instanceof
与定义的验证是否匹配。这在验证提供的对象是否是定义的验证对象子类时特别有用。
错误
除了内置的验证错误之外,Eloquent Interactions还在execute()
方法中支持自定义验证错误。这可以通过直接在Laravel验证器的errors()
方法上使用其自己的add()
方法来实现
public function execute() { $this->validator->errors()->add('entity', 'The entity object type is invalid.'); }
请注意,虽然在execute()
方法中添加自定义验证错误确实会将Outcome
标记为无效并返回预期的错误消息,但它不会停止交互执行,所以除非采取特殊步骤,否则execute()
方法中的任何业务逻辑都会按正常方式执行。
贡献
请阅读贡献指南。其中包含打开问题、编码标准和开发说明。
对于个人支持请求,请使用Gitter获取帮助。
版本控制
为了提高发布周期的透明度并努力保持向后兼容性,Eloquent Interactions遵循语义版本控制指南。有时我会犯错误,但我会尽可能遵守这些规则。
请参阅GitHub项目中的发布部分,以获取Eloquent Interactions每个发布版本的变更日志。
支持
问题跟踪器是报告错误、提出功能请求和提交拉取请求的首选渠道。
版权和许可
代码和文档版权所有2024年Zachary Flower。代码在MIT许可下发布。