NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky

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);   // VersionDiff

Metóda fasády → akcia

Menné priestory sú relatívne k RoundlyConsulting\Workflows\Actions:

Akciaexecute(…)Cesta cez fasádu
Definitions\CreateDefinitionAction(CreateDefinitionData $data): WorkflowDefinitiondefinitions()->create() / createWith()
Definitions\RestoreDefinitionAction(string $key, ?Model $owner): WorkflowDefinitiondefinitions()->restore()
Definitions\SyncDefinitionsAction(string $path, ?Model $owner = null, bool $publish = false, bool $dryRun = false): SyncReportdefinitions()->sync()
Definitions\SaveDraftAction(WorkflowDefinition $definition, array $graph, ?string $expectedChecksum = null): WorkflowVersiondefinition()->edit()
Definitions\DiscardDraftAction(WorkflowDefinition $definition): WorkflowDefinitiondefinition()->discardDraft()
Definitions\PublishVersionAction(WorkflowDefinition $definition, ?Model $by = null): WorkflowVersiondefinition()->publish()
Definitions\RetireDefinitionAction(WorkflowDefinition $definition): WorkflowDefinitiondefinition()->retire()
Definitions\ActivateDefinitionAction(WorkflowDefinition $definition): WorkflowDefinitiondefinition()->activate()
Definitions\ResolveReviewFlagAction(WorkflowDefinition $definition, string $node, string $path): WorkflowVersiondefinition()->resolveFlag()
Definitions\RotateWebhookAction(WorkflowDefinition $definition): WorkflowDefinitiondefinition()->rotateWebhook()
Versions\ValidateGraphAction(array $graph, ?string $subjectType = null, ?Model $owner = null, array $reviewFlags = [], ?string $definitionKey = null): ValidationReportversions()->validate(), definition()->validate(), GraphBuilder::validate()
Versions\DiffVersionsAction(WorkflowVersion $from, WorkflowVersion $to): VersionDiffversions()->diff()
Versions\OverlayAction(WorkflowVersion $version): OverlayReportversions()->overlay()
Versions\ExportTemplateAction(WorkflowVersion $version): TemplatePayloadversions()->export(), definition()->export()
Versions\ImportTemplateAction(TemplatePayload|array $payload, ?Model $owner = null, ?string $key = null): ImportResultversions()->import()
DryRun\DryRunAction(DryRunData $data): DryRunResultPendingDryRun::run() / explore()
Instances\StartInstanceAction(StartData $data): StartResultstart()->dispatch(), startWith(), for()->start(), definition()->start()
Instances\EmitEventAction(EmitData $data): EmitResultemit(), emitWith(), for()->emit()
Instances\ReceiveWebhookAction(string $hookId, array $payload, array $headers = []): StartResulttriggers()->webhook() and the inbound route
Instances\RetryInstanceAction(WorkflowInstance $instance): WorkflowInstanceinstances()->retry()
Instances\CancelInstanceAction(WorkflowInstance $instance, ?string $reason = null): WorkflowInstanceinstances()->cancel(), for()->cancelAll()
Instances\TouchSubjectAction(Model $subject): intfor()->touch()
Wake\WakeAction(?CarbonInterface $now = null, ?int $limit = null): WakeReportwake()
Maintenance\PruneAction(): PruneReportprune()

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ť

KontraktMetódyPredvolené / kde sa zapája
AuthorizesStepsauthorize(StepAuthorization $authorization): ResponseGateStepAuthorizer; authorization.authorizer
RestoresOwnerContextrun(?Model $owner, Closure $callback): mixedPrepojenie s teams, inak NullOwnerContext; owners.context
ChecksOwnerMembershipisMember(?Model $owner, Model $user): boolPrepojenie s teams, inak povolí všetkých; owners.membership
ResolvesRolesmembers(?Model $owner, string $role): arrayPrepojenie s teams, inak žiadne; parties.roles
TransitionAdapterattempt(…): TransitionOutcome; hasTransition(…): ?bool; stateAttributes(string $subjectClass): arrayPrepojenie s lifecycle, inak žiadny; adapters.transition
DeliversWebhooksdeliver(?Model $owner, string $endpoint, string $event, array $payload, string $idempotencyKey): int|stringŽiadny; adapters.webhooks zaregistruje krok webhook
BusinessCalendartimezone(), isBusinessDay($date), isOpenAt($instant), nextOpen($instant), nextClose($instant)weekdays, opening_hours:*; Workflows::calendars()->register()
CountsBusinessTimeaddBusinessDays(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).
HasWorkflowOwnerworkflowOwner(): ?ModelNa modeli subjektu: jeho vlastník, overuje sa ako prvý.
DescribesWorkflowSubjectdescribe(): SubjectTypeBuilderTriedy uvedené vo workflows.subjects.
WorkflowEventworkflowKey(), 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 kryptomien

Odoslaní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.