PlanExecutor
trait PlanExecutor
Execute compiled AttributePlans against validation data.
Architecture overview
Hypervel's validation uses a compiled single-path execution model:
-
Rules are compiled into AttributePlans by RuleCompiler — each rule becomes either an InlineCheck (fast, match-dispatched) or a DelegatedCheck (calls the existing validate*() method). Plans are cached worker-lifetime by RulePlanCache for Swoole performance.
-
Pre-optimizations run before execution when the context is provably non-mutating: exclude_if/exclude_unless pre-evaluation (eliminates excluded attributes before the loop) and batched exists/unique DB queries (collapses N queries into 1 per table:column).
-
This trait executes the compiled plans through a single loop. InlineChecks use simplified gating (all are non-implicit by design) and match-dispatch. DelegatedChecks call validateAttribute() directly — no duplication of upstream logic, zero maintenance burden for delegated rules.
Maintenance notes
- Adding a new inline-eligible rule requires changes in 3 places: CheckType (enum case + ruleName), RuleCompiler::tryInline(), and executeInline() below. Forgetting executeInline() fails PHPStan.
- DelegatedChecks require zero changes — they call validate*() directly.
- executeInline() arms must match the exact behavior of their corresponding validate*() methods in ValidatesAttributes. When an upstream method changes, the inline arm must be updated to match.
Mixed into Validator so it can call existing helpers on ValidatesAttributes (sizeOf, isValidEmail, compareDates, etc.) and access validator state ($this->data, $this->rules, $this->currentRule, etc.).
Methods
Execute all compiled plans against the validation data.
Execute an inline check against a value.
Details
at line 63
protected void
executeCompiledPlans(array $compiledPlans)
Execute all compiled plans against the validation data.
This is the ONLY execution path — every rule (inline or delegated) flows through this loop. Per-check fresh reads of $value and $exists match validateAttribute()'s per-rule getValue() call.
at line 142
protected bool
executeInline(InlineCheck $check, mixed $value, string $attribute)
Execute an inline check against a value.
Dispatches via exhaustive match over CheckType — no default arm. Adding a CheckType case without a handler here fails PHPStan and throws UnhandledMatchError at runtime. Silent passes are impossible.
Each arm replicates the exact logic of the corresponding validate*() method in ValidatesAttributes, but without parameter parsing, attribute context lookups, or dynamic method dispatch.