VOOZH about

URL: https://deepwiki.com/hypervel/validation/4-rule-system-architecture

⇱ Rule System Architecture | hypervel/validation | DeepWiki


Loading...
Menu

Rule System Architecture

Purpose and Scope

This document explains the flexible rule system that allows multiple ways to define validation logic in the Hypervel Validation package. It covers the overall architecture, rule definition formats, the Rule facade for creating rule objects, and how rules are compiled and executed.

For specific details on individual rule objects like Email, Password, and File, see Built-in Rule Objects. For creating custom validation logic, see Custom Validation Rules. For conditional rules that enable/disable based on runtime conditions, see Conditional and Dynamic Rules. For the interface contracts that define rule behavior, see Rule Interfaces and Contracts.

Overview

The rule system provides a unified architecture for defining validation constraints through multiple formats. Rules can be specified as simple strings ('required|email'), fluent rule objects (Rule::email()->validateMxRecord()), closures, or invokable classes. This flexibility allows developers to choose the appropriate level of expressiveness for their validation needs while maintaining consistent execution semantics.

The system consists of three primary layers:

  1. Definition Layer: The Rule facade and string-based rule syntax
  2. Compilation Layer: The ValidationRuleParser that normalizes and expands rules
  3. Execution Layer: The Validator class that orchestrates rule evaluation

Sources: src/Rule.php1-273

Rule Definition Formats

The validation system accepts rules in four distinct formats, each with specific use cases:

FormatExampleUse Case
String'required|email|max:255'Simple validations with minimal configuration
Pipe-Delimited String'email:rfc,dns|max:100'Built-in rules with parameters
Rule ObjectsRule::email()->validateMxRecord()Complex validations with fluent configuration
Closuresfunction($attribute, $value, $fail) { ... }Custom inline validation logic
Invokable Classesnew CustomRule()Reusable custom validation logic

These formats can be mixed within a single validation rule set. During compilation, all formats are normalized into a consistent internal representation.

Sources: src/Rule.php36-273 src/ValidationRuleParser.php1-900

Rule Type Taxonomy

The following diagram shows the complete taxonomy of rule types supported by the system:


Sources: src/Rule.php36-273 src/Rules/Email.php1-257 src/Rules/AnyOf.php1-100 src/ConditionalRules.php1-100

The Rule Facade

The Rule class at src/Rule.php36-273 serves as a static facade providing factory methods for creating rule objects. Each method returns a fluent builder instance that can be further configured before being passed to the validator.

Factory Method Mapping

The following table maps facade methods to their corresponding rule classes:

Facade MethodReturn TypePurpose
Rule::email()Rules\EmailEmail validation with RFC, DNS, and spoof checks
Rule::date()Rules\DateDate validation with format specification
Rule::dateTime()Rules\DateDateTime validation (preset format)
Rule::numeric()Rules\NumericNumeric validation with range constraints
Rule::file()Rules\FileFile upload validation with size/type checks
Rule::imageFile()Rules\ImageFileImage file validation with dimension checks
Rule::unique($table, $column)Rules\UniqueDatabase uniqueness constraint
Rule::exists($table, $column)Rules\ExistsDatabase existence constraint
Rule::in($values)Rules\InValue must be in allowed list
Rule::notIn($values)Rules\NotInValue must not be in disallowed list
Rule::contains($values)Rules\ContainsArray must contain specified values
Rule::doesntContain($values)Rules\DoesntContainArray must not contain specified values
Rule::requiredIf($callback)Rules\RequiredIfRequired if condition is true
Rule::excludeIf($callback)Rules\ExcludeIfExclude from validated data if condition is true
Rule::prohibitedIf($callback)Rules\ProhibitedIfProhibited if condition is true
Rule::anyOf($rules)Rules\AnyOfAt least one rule must pass
Rule::when($condition, $rules)ConditionalRulesApply rules if condition is true
Rule::unless($condition, $rules)ConditionalRulesApply rules if condition is false
Rule::forEach($callback)NestedRulesApply nested rules to array elements
Rule::dimensions($constraints)Rules\DimensionsImage dimension constraints
Rule::enum($type)Rules\EnumEnum value validation
Rule::array($keys)Rules\ArrayRuleArray structure validation

Sources: src/Rule.php40-248

Example: Email Rule Configuration

The Email rule object demonstrates the fluent builder pattern used throughout the rule system:


Each method modifies internal boolean flags src/Rules/Email.php22-32 that control which validation strategies are applied during execution src/Rules/Email.php193-228

Sources: src/Rules/Email.php17-257 src/Rule.php193-196

Rule Compilation Process

Before rules are executed, they undergo a compilation phase handled by the ValidationRuleParser. This diagram illustrates the compilation pipeline:


Sources: src/ValidationRuleParser.php1-900 src/Rule.php253-272

Wildcard Rule Expansion

When rules use wildcard syntax (e.g., items.*.email), the parser expands them to match all existing data keys. For example:

Input Data: ['items' => [0 => [...], 1 => [...]]]
Rule: 'items.*.email' => 'required|email'

Expanded To:
- 'items.0.email' => 'required|email'
- 'items.1.email' => 'required|email'

This expansion occurs in ValidationRuleParser::explodeWildcardRules() which iterates through the data structure to find all matching paths.

Sources: src/ValidationRuleParser.php200-350

Dot Notation Escaping

To prevent conflicts between attribute names containing dots and nested array notation, the parser escapes literal dots in keys:

'user.name' => 'user__dot__name' (literal key)
'user.name' => 'user' => ['name'] (nested array)

This escaping is handled by replacePlaceholderDots() and reversed later during message generation.

Sources: src/ValidationRuleParser.php400-450

Rule Execution Strategy

The validator employs a type-based execution strategy to handle different rule formats. This diagram shows the decision flow:


Sources: src/Validator.php1-2500 src/Concerns/ValidatesAttributes.php1-3000

String Rule Execution

String rules are resolved to methods in the ValidatesAttributes trait. The validator uses the following pattern:

  1. Parse rule name and parameters: 'max:255' → method: validateMax, parameters: [255]
  2. Check if method exists: method_exists($this, 'validateMax')
  3. Call method: $this->validateMax($attribute, $value, [255])

The method returns true if validation passes, false otherwise.

Sources: src/Validator.php1500-1600 src/Concerns/ValidatesAttributes.php100-150

Object Rule Execution

Object rules implement the Rule interface src/Contracts/Rule.php1-20 which requires a passes() method. The execution sequence:

  1. Check if rule implements DataAwareRule → call setData()
  2. Check if rule implements ValidatorAwareRule → call setValidator()
  3. Call passes($attribute, $value) → returns boolean
  4. If failed, call message() → returns string or array of error messages

The Email rule demonstrates this pattern at src/Rules/Email.php166-188 and src/Rules/Email.php233-236

Sources: src/Validator.php1700-1800 src/Rules/Email.php17-257 src/Contracts/Rule.php1-20

Context Injection

Rules implementing DataAwareRule or ValidatorAwareRule receive validation context before execution:

InterfaceMethodPurpose
DataAwareRulesetData(array $data)Access all validation data
ValidatorAwareRulesetValidator(ValidatorContract $validator)Access validator instance

This allows rules to make decisions based on other attributes or validator configuration. The Email rule uses both interfaces src/Rules/Email.php17 to access custom messages and attributes src/Rules/Email.php177-178

Sources: src/Contracts/DataAwareRule.php1-20 src/Contracts/ValidatorAwareRule.php1-20 src/Rules/Email.php37-42 src/Rules/Email.php241-256

Closure and Invokable Adapters

Closures and invokable classes are wrapped in adapter objects that implement the Rule interface:


The adapters translate the closure/invokable calling convention into the standard passes() method signature, allowing uniform execution logic in the validator.

Sources: src/ClosureValidationRule.php1-100 src/InvokableValidationRule.php1-100

Implicit vs Explicit Rules

Rules are classified as either implicit or explicit, which determines whether they execute for missing attributes:

ClassificationBehaviorExample Rules
ExplicitOnly validates if attribute is present in dataemail, max, regex
ImplicitValidates even if attribute is missingrequired, accepted, filled

A rule is implicit if it implements the ImplicitRule interface. This classification is checked via:


The implicitRules property contains string rule names like 'required', 'accepted', and 'present'.

Sources: src/Validator.php200-250 src/Contracts/ImplicitRule.php1-15

Dependent and Exclude Rules

Two additional rule classifications affect validation behavior:

Dependent Rules

Dependent rules have parameters that reference other attributes using wildcards. Before execution, these wildcards are replaced with actual attribute names. For example:

Rule: 'required_with:items.*'
Data: ['items' => [0 => 'a', 1 => 'b']]

Expanded: 'required_with:items.0,items.1'

Dependent rules include: required_with, required_without, same, different, before, after, etc.

Sources: src/Validator.php300-350

Exclude Rules

Exclude rules remove attributes from the final validated data set. Rules implementing this behavior include:

  • exclude - Always excludes the attribute
  • exclude_if - Excludes if condition is true
  • exclude_unless - Excludes unless condition is true
  • exclude_with - Excludes if another attribute is present
  • exclude_without - Excludes if another attribute is missing

After validation completes, attributes marked for exclusion are filtered from the validated data returned to the user.

Sources: src/Validator.php2200-2250

Rule Compilation Method

The static Rule::compile() method src/Rule.php253-272 provides a utility for compiling rules outside the standard validator lifecycle:


This method:

  1. Creates a ValidationRuleParser instance
  2. Normalizes the attribute and rules into an array structure
  3. Expands wildcards based on the provided data
  4. Returns a compiled object with rules and wildcards properties

This is primarily used internally by the validator but can be useful for testing or introspection.

Sources: src/Rule.php253-272 src/ValidationRuleParser.php100-200

Summary

The rule system architecture provides flexibility through:

  1. Multiple Definition Formats: Strings, objects, closures, and invokables
  2. Unified Facade: The Rule class provides consistent factory methods
  3. Flexible Execution: Type-based strategy pattern handles all rule formats
  4. Context Injection: Rules can access validation data and validator configuration
  5. Smart Compilation: Wildcards, dot notation, and conditional rules are resolved before execution
  6. Classification System: Implicit, dependent, and exclude rules modify validation behavior

This architecture enables developers to choose the appropriate abstraction level for each validation scenario while maintaining consistent execution semantics and extensibility.

For implementation details of specific rule types, see Built-in Rule Objects. For creating custom rules, see Custom Validation Rules. For the interface contracts, see Rule Interfaces and Contracts.

Sources: src/Rule.php1-273 src/Rules/Email.php1-257 src/Validator.php1-2500 src/ValidationRuleParser.php1-900