ionews / light-service-php
通过一系列简单操作实现复杂动作的简单接口
Requires (Dev)
- phpunit/phpunit: *
- satooshi/php-coveralls: dev-master
This package is not auto-updated.
Last update: 2024-09-28 16:09:59 UTC
README
一个小型软件,旨在强制在PHP应用程序中实施SRP,被认为“轻量级”且不使用任何依赖项。高度基于两个ruby gems提出的思想
概念
每个动作应该有一个单一的责任,必须在 perform
方法中实现。一个动作可以访问数据库、发送电子邮件、调用服务等等。当执行一个动作时,它会接收到一个可以读取和修改的上下文。
要执行更复杂的操作,您必须使用组织器链接多个动作,这些动作在执行期间将共享相同的上下文。实际上,组织器不过是一个具有特定实现的动作,这意味着动作和组织器共享完全相同的接口。这很有用,因此您可以将组织器作为动作包含在另一个组织器中。
动作示例
class GenerateRandomPassword extends Action { protected function perform() { $length = 8; $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $password = ''; for ($i = 0; $i < $length; $i++) { $password .= $chars[rand(0, strlen($chars) - 1)]; } $this->context->password = $password; } } class UpdateUserPassword extends Action { protected function perform() { $user_id = $this->context->user_id; $password = $this->context->password; // access the database using the method of your choice and update the password } }
组织器示例
class ResetUserPassword extends Organizer { protected $organize = ['GenerateRandomPassword', 'UpdateUserPassword', 'EmailUserWithPassword']; }
调用示例(从MVC控制器中)
class UserController extends BaseController { public function resetPassword() { $result = ResetUserPassword::execute(['user_id' => $this->request->id]); if ($result->success()) { // use $result->getContext() to access the results and redirect the app } else { // error, use $result->getFailureMessage() to access any failure message } } }
请注意,您不应该在应用程序的每个地方都使用这种方法,而只在其真正复杂的部分中使用。
失败、停止和异常
一个动作可能会失败,意味着它无法实现其目标。要使一个动作失败,只需调用 fail
方法(可选地传递一个消息)。
class SomeAction extends Action { protected function perform() { $this->fail('Oh noes'); } } $result = SomeAction::execute([]); $result->success(); // false $result->failure(); // true $result->halted(); // false $result->getFailureMessage(); // 'Oh noes'
如果动作在组织器内部执行并失败,它将阻止后续动作的执行。如果动作实现了 rollback
方法,则在后续动作失败后调用它。例如:如果 EmailUserWithPassword
无法向用户发送电子邮件,我们可以在 UpdateUserPassword
中实现一个 rollback
方法来撤销更新。在 rollback
方法中,您可以以与 perform
相同的方式访问上下文。
class UpdateUserPassword extends Action { protected function perform() { $user_id = $this->context->user_id; $password = $this->context->password; // access the database using the method of your choice and update the password } protected function rollback() { // undo the update password } }
除非您真的知道自己在做什么,否则不要重新实现组织器的 rollback
方法。
可以使用 halt
停止执行链而不会失败:基本它会阻止执行后续的动作,但结果仍然是成功的。您可以使用 halted
方法测试动作/组织器是否已停止。
class SomeAction extends Action { protected function perform() { $this->halt(); } } $result = SomeAction::execute([]); $result->success(); // true $result->failure(); // false $result->halted(); // true
在执行动作时发生的所有异常都会自动捕获并传递给 caught
方法。默认情况下,动作会重新抛出,另一方面,组织器首先调用 rollback
方法然后再重新抛出。这样做是为了在异常传播之前回滚所有执行的动作。您可以通过重新实现 caught
方法来更改此行为。
之前和之后
如果您需要在执行之前进行任何设置,可以实施一个 before
方法。如果在 before
中调用 fail
方法,则 perform
将永远不会被调用。同样,您可以实施一个 after
方法,以便可以在执行后进行任何清理,但请注意,如果 before
或 perform
失败,它将永远不会被调用。
class SomeAction extends Action { protected function before() { // any setup } protected function perform() { // perform } protected function after() { // cleanup } }
期望和承诺
可以为每个动作定义期望和承诺。如果动作有一组期望,那么如果这些期望未满足,它将自动失败。
class UpdateUserPassword extends Action { protected $expects = ['user_id', 'password']; protected function perform() { $user_id = $this->context->user_id; $password = $this->context->password; // access the database using the method of your choice and update the password } } $result = UpdateUserPassword::execute(['user_id' => 1]); $result->success(); // false $result->getFailureMessage(); // 'Expectations were not met'
同样,如果定义了一组承诺,并且这些承诺在执行结束时不在上下文中,动作将失败。
class GenerateRandomPassword extends Action { protected $promises = ['password']; protected function perform() { $length = 8; $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'; $password = ''; for ($i = 0; $i < $length; $i++) { $password .= $chars[rand(0, strlen($chars) - 1)]; } //$this->context->password = $password; } } $result = GenerateRandomPassword::execute([]); $result->success(); // false $result->getFailureMessage(); // 'Promises were not met'
此功能特别有用,可以显式定义动作之间的接口。
迭代器动作
它是一个将在数组上执行的动作。
class SomeAction extends IteratorAction { protected $over = 'key_of_the_array_in_context' protected function each($key, $value) { ... } }
需求
- PHP 5.3+
安装和用法
贡献
你知道怎么做!
许可证
在GPLv2下发布