DI a akcie
Fasáda je odporúčaná voľba, nie jediná cesta. Každá operácia je akcia, manažér sprístupňuje každú z nich a fasáda je nadstavba nad manažérom — všetky tri spôsoby spúšťajú rovnaký kód. Manažér je RoundlyConsulting\Workflows\WorkflowsManager, koreň fasády, registrovaný ako singleton v kontajneri a injektovateľný podľa názvu triedy:
use RoundlyConsulting\Workflows\Actions\Instances\StartInstanceAction;
use RoundlyConsulting\Workflows\DataTransferObjects\StartData;
use RoundlyConsulting\Workflows\Facades\Workflows;
use RoundlyConsulting\Workflows\WorkflowsManager;
// Facade
$result = Workflows::start('purchase-approval', $request, $team)->input(['reason' => 'laptops'])->by($user)->dispatch();
// Dependency injection — the same API
public function __construct(private WorkflowsManager $workflows) {}
$result = $this->workflows->start('purchase-approval', $request, $team)->input(['reason' => 'laptops'])->by($user)->dispatch();
// The raw action (not recorded by the fake)
$result = app(StartInstanceAction::class)->execute(new StartData('purchase-approval', $request, $team, ['reason' => 'laptops'], $user));Trait HasWorkflows je štvrtý vstup k tomu istému manažérovi — $request->workflows()->start('purchase-approval')->dispatch() sa naň deleguje, takže aj tieto volania fake vidí.
Injektovanie manažéra
use RoundlyConsulting\Workflows\Exceptions\WorkflowsException;
use RoundlyConsulting\Workflows\WorkflowsManager;
final class RetryWorkflowController
{
public function __invoke(WorkflowsManager $workflows, string $ulid)
{
$instance = $workflows->instances()->find($ulid) ?? abort(404);
try {
$workflows->instances()->retry($instance);
} catch (WorkflowsException $e) {
return response()->json(['code' => $e->errorCode(), 'message' => $e->getMessage()], $e->status());
}
return response()->noContent();
}
}Workflows::fake() vymení manažéra za Testing\WorkflowsFake — jeho podtriedu — za fasádou aj v kontajneri, takže fake pokryje aj kód, ktorý injektuje WorkflowsManager.
Volanie akcie
Každá operácia je final readonly akcia s jednou metódou execute(), získaná z kontajnera — ak ju chcete prepísať, zaregistrujte vlastnú podtriedu. Priame volania akcií fake nezaznamenáva; kód aplikácie bežne volá fasádu alebo manažéra:
use RoundlyConsulting\Workflows\Actions\Instances\RetryInstanceAction;
use RoundlyConsulting\Workflows\Actions\Versions\DiffVersionsAction;
app(RetryInstanceAction::class)->execute($instance);
$diff = app(DiffVersionsAction::class)->execute($v2, $v3); // VersionDiffMetóda fasády → akcia
Menné priestory sú relatívne k RoundlyConsulting\Workflows\Actions:
| Akcia | execute(…) | Cesta cez fasádu |
|---|---|---|
Definitions\CreateDefinitionAction | (CreateDefinitionData $data): WorkflowDefinition | definitions()->create() / createWith() |
Definitions\RestoreDefinitionAction | (string $key, ?Model $owner): WorkflowDefinition | definitions()->restore() |
Definitions\SyncDefinitionsAction | (string $path, ?Model $owner = null, bool $publish = false, bool $dryRun = false): SyncReport | definitions()->sync() |
Definitions\SaveDraftAction | (WorkflowDefinition $definition, array $graph, ?string $expectedChecksum = null): WorkflowVersion | definition()->edit() |
Definitions\DiscardDraftAction | (WorkflowDefinition $definition): WorkflowDefinition | definition()->discardDraft() |
Definitions\PublishVersionAction | (WorkflowDefinition $definition, ?Model $by = null): WorkflowVersion | definition()->publish() |
Definitions\RetireDefinitionAction | (WorkflowDefinition $definition): WorkflowDefinition | definition()->retire() |
Definitions\ActivateDefinitionAction | (WorkflowDefinition $definition): WorkflowDefinition | definition()->activate() |
Definitions\ResolveReviewFlagAction | (WorkflowDefinition $definition, string $node, string $path): WorkflowVersion | definition()->resolveFlag() |
Definitions\RotateWebhookAction | (WorkflowDefinition $definition): WorkflowDefinition | definition()->rotateWebhook() |
Versions\ValidateGraphAction | (array $graph, ?string $subjectType = null, ?Model $owner = null, array $reviewFlags = [], ?string $definitionKey = null): ValidationReport | versions()->validate(), definition()->validate(), GraphBuilder::validate() |
Versions\DiffVersionsAction | (WorkflowVersion $from, WorkflowVersion $to): VersionDiff | versions()->diff() |
Versions\OverlayAction | (WorkflowVersion $version): OverlayReport | versions()->overlay() |
Versions\ExportTemplateAction | (WorkflowVersion $version): TemplatePayload | versions()->export(), definition()->export() |
Versions\ImportTemplateAction | (TemplatePayload|array $payload, ?Model $owner = null, ?string $key = null): ImportResult | versions()->import() |
DryRun\DryRunAction | (DryRunData $data): DryRunResult | PendingDryRun::run() / explore() |
Instances\StartInstanceAction | (StartData $data): StartResult | start()->dispatch(), startWith(), for()->start(), definition()->start() |
Instances\EmitEventAction | (EmitData $data): EmitResult | emit(), emitWith(), for()->emit() |
Instances\ReceiveWebhookAction | (string $hookId, array $payload, array $headers = []): StartResult | triggers()->webhook() and the inbound route |
Instances\RetryInstanceAction | (WorkflowInstance $instance): WorkflowInstance | instances()->retry() |
Instances\CancelInstanceAction | (WorkflowInstance $instance, ?string $reason = null): WorkflowInstance | instances()->cancel(), for()->cancelAll() |
Instances\TouchSubjectAction | (Model $subject): int | for()->touch() |
Wake\WakeAction | (?CarbonInterface $now = null, ?int $limit = null): WakeReport | wake() |
Maintenance\PruneAction | (): PruneReport | prune() |
Interné (stavebné bloky enginu, kód aplikácie ich nikdy nevolá): Engine\RunStepAction, Engine\ResumeStepAction, Engine\RecordStepResultAction, Engine\FireEscalationAction, Instances\SignalAction, Wake\EvaluateSchedulesAction, Wake\ReclaimAction.
Kontrakty, ktoré môžete implementovať
| Kontrakt | Metódy | Predvolené / kde sa zapája |
|---|---|---|
AuthorizesSteps | authorize(StepAuthorization $authorization): Response | GateStepAuthorizer; authorization.authorizer |
RestoresOwnerContext | run(?Model $owner, Closure $callback): mixed | Prepojenie s teams, inak NullOwnerContext; owners.context |
ChecksOwnerMembership | isMember(?Model $owner, Model $user): bool | Prepojenie s teams, inak povolí všetkých; owners.membership |
ResolvesRoles | members(?Model $owner, string $role): array | Prepojenie s teams, inak žiadne; parties.roles |
TransitionAdapter | attempt(…): TransitionOutcome; hasTransition(…): ?bool; stateAttributes(string $subjectClass): array | Prepojenie s lifecycle, inak žiadny; adapters.transition |
DeliversWebhooks | deliver(?Model $owner, string $endpoint, string $event, array $payload, string $idempotencyKey): int|string | Žiadny; adapters.webhooks zaregistruje krok webhook |
BusinessCalendar | timezone(), isBusinessDay($date), isOpenAt($instant), nextOpen($instant), nextClose($instant) | weekdays, opening_hours:*; Workflows::calendars()->register() |
CountsBusinessTime | addBusinessDays(CarbonImmutable $from, int $days), addBusinessTime(CarbonImmutable $from, int $seconds) | Voliteľné pre kalendár, ktorý počíta sám (kalendáre opening-hours to robia). |
HasWorkflowOwner | workflowOwner(): ?Model | Na modeli subjektu: jeho vlastník, overuje sa ako prvý. |
DescribesWorkflowSubject | describe(): SubjectTypeBuilder | Triedy uvedené vo workflows.subjects. |
WorkflowEvent | workflowKey(), workflowSubject(), workflowPayload(), workflowUser(), workflowIdempotencyKey() | Udalosť hostiteľa, ktorá sa opisuje sama (listen() alebo '*'). |
Väzba AuthorizesSteps, RestoresOwnerContext alebo ChecksOwnerMembership v kontajneri, zaregistrovaná po provideri balíka, má prednosť pred triedou z konfigurácie.
Prejavte lásku k open source
Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.
Ďalšie spôsoby podpory vrátane kryptomienOdoslaním daru súhlasíte s našimi podmienkami prijímania darov.
Chcete to zabudovať do svojho produktu?
Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.