Subjekty, vlastníci a strany
Typy subjektov
Subjekt je model, ktorého sa inštancia týka. Každý typ zaregistrujte raz, v metóde boot() service providera. Polia sú to, čo smú podmienky, odkazy a set_field čítať a zapisovať — nič iné na modeli:
use RoundlyConsulting\Workflows\Facades\Workflows;
Workflows::subjects()->register(
Workflows::subject('purchase_request', PurchaseRequest::class) // SubjectTypeBuilder
->label('Purchase request')
->ownedBy('team') // relation or attribute naming the owner
->field('amount', 'decimal', 'Amount')
->field('status', 'enum', 'Status', options: PurchaseStatus::class) // enum class or list
->field('requester', 'party', 'Requester') // relation to a user
->field('approver_manager', 'party', "Approver's manager", path: 'approver.manager')
->field('due_on', 'date', 'Due on')
->field('priority', 'string', 'Priority', writable: true) // set_field may write it
->ability('update'), // the ability set_field checks on this type
);- Typy polí: string, text, integer, decimal, boolean, date, datetime, enum, party, list. Názvy zodpovedajú ^[a-z][a-z0-9_]{0,63}$.
- Čítanie ide cez registrovanú cestu (atribút alebo reláciu s bodkou). Neregistrované atribúty sa nikdy nečítajú. Enumy sa čítajú ako ich hodnota, dátumy sa prevedú do časového pásma verzie (dátum o polnoci si zachová uložený kalendárny deň) a desatinné čísla sa čítajú ako reťazce.
- Definície, šablóny, resources aj API ukladajú a zobrazujú kľúč z registra (purchase_request), nikdy názov triedy.
- Definícia nemusí mať typ subjektu (subjectType: null): jej inštancie potom bežia bez subjektu.
Namiesto registrácie v provideri môžete do workflows.subjects uviesť triedy, ktoré implementujú Contracts\DescribesWorkflowSubject:
use RoundlyConsulting\Workflows\Builders\SubjectTypeBuilder;
use RoundlyConsulting\Workflows\Contracts\DescribesWorkflowSubject;
use RoundlyConsulting\Workflows\Facades\Workflows;
final class PurchaseRequestSubject implements DescribesWorkflowSubject
{
public function describe(): SubjectTypeBuilder
{
return Workflows::subject('purchase_request', PurchaseRequest::class)
->label('Purchase request')
->ownedBy('team')
->field('amount', 'decimal', 'Amount');
}
}
// config/workflows.php
'subjects' => [App\Workflows\PurchaseRequestSubject::class],Z registra čerpá výber polí v editore:
Workflows::subjects()->find('purchase_request'); // ?SubjectTypeDefinition
Workflows::subjects()->all(); // array<string, SubjectTypeDefinition>
Workflows::subjects()->export('purchase_request'); // key, label, fields with type, label, writable, optionsTrait HasWorkflows
$request->workflows()->start('purchase-approval', $team)->dispatch();
$request->workflows()->emit('purchase_request.submitted', ['note' => 'urgent']);
$request->workflows()->instances(); // cursor-paginated history, newest first
$request->workflows()->running(); // running or waiting instances
$request->workflows()->cancelAll('withdrawn');
$request->workflows()->touch(); // re-evaluate its condition waits
$request->workflowInstances(); // the morphMany relation
// The same handle without the trait:
Workflows::for($request)->running();Po commite aktualizácie trait spraví touch subjektu, ak má čakajúce podmienkové čakania — no len vtedy, keď aktualizácia zmenila atribút registrovaného poľa alebo cudzí kľúč poľa typu belongs-to, takže bežné uloženie nepridá žiadny dopyt. Po zmazaní subjects_on_deleted = cancel (predvolené) zruší jeho bežiace inštancie; keep ich ponechá (zlyhajú so subject_missing, keď subjekt najbližšie potrebujú). Všetko ide cez manažéra, takže to Workflows::fake() vidí.
Vlastníci
Vlastník je tenant, ktorému definícia patrí — tím, firma. Null = celá aplikácia. Vlastník subjektu sa určuje v tomto poradí:
- Contracts\HasWorkflowOwner::workflowOwner() na subjekte;
- ownedBy(relation|attribute) typu subjektu;
- prepojenie s teams (BelongsToTeam / ScopedToTeam: stĺpec tímu);
- inak neznámy.
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Workflows\Contracts\HasWorkflowOwner;
class PurchaseRequest extends Model implements HasWorkflowOwner
{
public function workflowOwner(): ?Model
{
return $this->department->company; // checked before ownedBy() and the teams bridge
}
}Definícia pre celú aplikáciu prijme akýkoľvek subjekt. Definícia s vlastníkom prijme subjekt len vtedy, keď má jeho vlastník rovnakú morph triedu a kľúč; neznámy vlastník je nezhoda (fail closed). Definíciu s vlastníkom, ktorej typ subjektu nemá určenie vlastníka, nemožno publikovať (subject_owner_unresolvable).
Vlastník inštancie je vlastník definície, alebo — pri definícii pre celú aplikáciu — vlastník subjektu určený pri spustení. Všetky ďalšie kontroly aj kontext vlastníka používajú vlastníka inštancie. Ak sa subjekt počas behu presunie k inému vlastníkovi, ďalší krok zlyhá s owner_mismatch ešte pred spustením handlera. Typy vlastníkov sa registrujú ako subjekty, aby sa dali overiť odkazy owner.<field>:
// Owner types register like subjects, so owner.<field> refs validate.
Workflows::subjects()->register(
Workflows::subject('team', Team::class)->ownerType()->field('plan', 'string', 'Plan'),
);Strany
Schvaľovatelia, príjemcovia a ciele eskalácie sú odkazy na strany, rozlíšené podľa kind:
{"kind": "user", "id": 12}
{"kind": "field", "field": "subject.requester"}
{"kind": "role", "role": "legal"}
{"kind": "triggered_by"}| Druh | JSON | Vyhodnotí sa na | Špecifické pre vlastníka |
|---|---|---|---|
user | {"kind":"user","id":12} | Model používateľa (workflows.parties.user_model, predvolene auth.providers.users.model). | áno |
field | {"kind":"field","field":"subject.requester"} | Registrované pole typu party na subjekte alebo vlastníkovi. | nie |
role | {"kind":"role","role":"legal"} | ResolvesRoles::members($owner, $role) — prepojenie s teams alebo workflows.parties.roles. | nie |
triggered_by | {"kind":"triggered_by"} | Ten, kto inštanciu spustil. | nie |
- Členstvo: strany user, field a triggered_by musia prejsť Contracts\ChecksOwnerMembership::isMember($owner, $user) (workflows.owners.membership; prepojenie s teams vyžaduje aktívne členstvo; bez neho je členom každý).
- Bez vyhodnocovania rolí sa strany typu role pri publikovaní odmietnu (roles_unavailable).
- Duplicity sa odstránia podľa kľúča; mäkko zmazaní používatelia sa preskočia.
- Prázdne vyhodnotenie nikdy neznamená „ktokoľvek“: fáza schvaľovania bez schvaľovateľov zlyhá s no_approvers; krok notify bez príjemcov sa dokončí s recipients: 0.
- Hodnoty špecifické pre vlastníka (strany typu user) sa pri importe šablóny pre iného vlastníka vymažú a označia na kontrolu.
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.