工作流和状态机
工作流
工作流是你应用程序中流程的模型。它可以是博客文章从草稿到审查和发布的流程。另一个例子是用户提交一系列不同的表单来完成任务。这些流程最好与你的模型分离,并在配置中定义。
工作流的**定义**包括位置和从一个位置到另一个位置的动作。这些动作被称为**转换**。工作流还需要知道每个对象在工作流中的位置。**标记存储**将当前位置写入对象的属性。
注意
上面的术语在讨论工作流和 Petri 网 时常用。
示例
最简单的工作流看起来像这样。它包含两个位置和一个转换。

当工作流描述真实的业务案例时,可能会更复杂。下面的工作流描述了填写职位申请的流程。

在这个例子中,当你填写职位申请时,根据你申请的职位,有 4 到 7 个步骤。有些职位需要用户回答性格测试、逻辑测试和/或正式要求。有些职位不需要。GuardEvent
用于决定特定申请允许的后续步骤。
通过像这样定义工作流,可以概览流程的样子。流程逻辑不会与控制器、模型或视图混合在一起。步骤的顺序可以通过仅更改配置来更改。
状态机
状态机是工作流的子集,其目的是保持模型的某个状态。它们之间最重要的区别是
- 工作流可以同时处于多个位置,而状态机不能;
- 为了应用转换,工作流要求对象处于转换的所有先前位置,而状态机仅要求对象至少处于这些位置之一。
示例
拉取请求从初始的“start”状态开始,然后进入“test”状态,例如在持续集成堆栈上运行测试。完成此操作后,拉取请求处于“review”状态,贡献者可以在此状态下要求更改、拒绝或接受拉取请求。在任何时候,你也可以“update”拉取请求,这将导致另一次持续集成运行。

以下是拉取请求状态机的配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
# config/packages/workflow.yaml
framework:
workflows:
pull_request:
type: 'state_machine'
marking_store:
type: 'method'
property: 'currentPlace'
# The "supports" option is useful only if you are using Twig functions ('workflow_*')
supports:
- App\Entity\PullRequest
initial_marking: start
places:
- start
- coding
- test
- review
- merged
- closed
transitions:
submit:
from: start
to: test
update:
from: [coding, test, review]
to: test
wait_for_review:
from: test
to: review
request_change:
from: review
to: coding
accept:
from: review
to: merged
reject:
from: review
to: closed
reopen:
from: closed
to: review
提示
如果你的转换定义了工作流中使用的所有位置,则可以省略 places
选项。Symfony 将自动从转换中提取位置。
7.1
Symfony 7.1 中引入了对省略 places
选项的支持。
Symfony 会自动为你配置中定义的每个工作流 (Workflow) 或状态机 (StateMachine) 创建一个服务。你可以通过使用服务自动装配并在类中使用 camelCased 工作流名称 + Workflow 作为参数名称,在类中使用工作流。如果是状态机类型,请使用 camelCased 工作流名称 + StateMachine
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
// ...
use App\Entity\PullRequest;
use Symfony\Component\Workflow\WorkflowInterface;
class SomeService
{
public function __construct(
// Symfony will inject the 'pull_request' state machine configured before
private WorkflowInterface $pullRequestStateMachine,
) {
}
public function someMethod(PullRequest $pullRequest): void
{
$this->pullRequestStateMachine->apply($pullRequest, 'wait_for_review', [
'log_comment' => 'My logging comment for the wait for review transition.',
]);
// ...
}
// ...
}
自动和手动验证
在缓存预热期间,Symfony 会验证配置文件中定义的工作流和状态机。如果你的工作流或状态机是以编程方式而不是在配置文件中定义的,你可以使用 WorkflowValidator 和 StateMachineValidator 来验证它们
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
// ...
use Symfony\Component\Workflow\Definition;
use Symfony\Component\Workflow\StateMachine;
use Symfony\Component\Workflow\Validator\StateMachineValidator;
$states = ['created', 'activated', 'deleted'];
$stateTransitions = [
new Transition('activate', 'created', 'activated'),
// This duplicate event "from" the "created" state is invalid
new Transition('activate', 'created', 'deleted'),
new Transition('delete', 'activated', 'deleted'),
];
// No validation is done upon initialization
$definition = new Definition($states, $stateTransitions);
$validator = new StateMachineValidator();
// Throws InvalidDefinitionException in case of an invalid definition
$validator->validate($definition, 'My First StateMachine');