aegisora / rule-contract
Contracts for rule-based validation in Aegisora ecosystem
Requires
- php: >=7.4
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.6
- squizlabs/php_codesniffer: ^4.0
README
Rule Contract defines the core abstractions for building validation rules in the Aegisora ecosystem.
It provides:
- a minimal, stable, and framework-agnostic contract that allows rules to be shared across packages and projects
- a strict contract for implementing rules
- consistent result handling
- unified exception management
โจ Features
- ๐น Lightweight, framework-agnostic design and dependency-free
- ๐น Stable contract for validation rules
- ๐น Unified validation result structure
- ๐น Immutable ruleโcontext binding and type-safe collection
- ๐น Safe exception handling with execution wrapping
- ๐น Automatic rule code generation
- ๐น Supports both simple and complex rules
- ๐น Designed for extensibility
- ๐น Compatible with Aegisora ecosystem (
guardian,rules, etc.)
๐ฆ Installation
composer require aegisora/rule-contract
๐ Core Concept
Each rule:
- receives a
Context - performs validation logic
- returns a
Result - never returns raw booleans
- never throws unstructured exceptions
This ensures predictable and testable validation flow.
๐๏ธ Basic Usage
Creating a Rule
Extend the abstract Rule class (simple example):
class UserAgeRule extends Rule { protected function executeValidate(Context $context): Result { $age = $context->getValue(); if ($age < 18) { return $this->getDefaultInvalidResult(); } return $this->getDefaultValidResult(); } }
Running a Rule
$rule = new UserAgeRule(); $result = $rule->validate(Context::create(20)); if ($result->isValid()) { // valid }
๐๏ธ Architecture
RuleInterface
Defines the contract for all rules:
validate(Context $context): Result
May throw:
InvalidRuleContextExceptionRuleExceptionRuleExecutionException
Rule (Abstract Class)
Base implementation that provides:
- Safe execution layer
- wraps execution in
try/catch - rethrows domain exceptions as-is
- wraps unexpected errors into
RuleExecutionException
- wraps execution in
- Default helpers
getDefaultValidResult()getDefaultInvalidResult()
- Automatic rule code generation - generates
snake_casecode from class name:UserAgeRuleโuser_age_rule
Execution Flow
validate()is calledexecuteValidate()runs- Result handling:
RuleExceptionโ rethrownThrowableโ wrapped intoRuleExecutionException
Resultis returned
Context
Encapsulates input data for rule execution.
Context::create($value);
- stores
mixedvalue - provides
getValue()access
Used to decouple rules from application structures.
Result
Standardized validation result object.
Structure
isValid: boolfailedRuleCode: ?string
Factory methods
Result::valid()Result::invalid('rule_code')
RuleContext
Immutable binding of a rule and the context it should be validated against.
RuleContext::create($rule, $context);
- stores a
RuleInterfaceand aContext - provides
getRule(): RuleInterface - provides
getContext(): Context - provides
getContextValue()shortcut forgetContext()->getValue()
RuleContext::createFromValue($rule, $value);
- shortcut that wraps a raw
mixed$valueinto aContextinternally - equivalent to
RuleContext::create($rule, Context::create($value))
Useful for passing around a rule together with its input as a single unit.
$ruleContext = RuleContext::createFromValue($rule, 20); $result = $ruleContext->getRule()->validate($ruleContext->getContext());
RuleContextCollection
Immutable, type-safe collection of RuleContext objects.
RuleContextCollection::create($ruleContext1, $ruleContext2, ...);
- accepts only
RuleContextinstances (enforced via variadic type hint) - implements
Iteratorโ can be traversed withforeach - implements
Countableโ usable withcount() - provides
toArray(): RuleContext[] - provides
count(): int - provides
isEmpty(): bool
$collection = RuleContextCollection::create( RuleContext::create($ruleA, Context::create($valueA)), RuleContext::create($ruleB, Context::create($valueB)), ); foreach ($collection as $ruleContext) { $result = $ruleContext->getRule()->validate($ruleContext->getContext()); // ... }
Exception Handling
RuleException
Base exception for all rule-related errors.
InvalidRuleContextException
Thrown when context is invalid for a rule.
RuleExecutionException
Thrown when unexpected runtime error occurs during rule execution.
Contains:
- rule class name (
getRuleClassName()) - original exception
Design Principles
This package enforces:
- predictable execution flow
- strict separation of concerns
- consistent validation results
- safe error boundaries
- framework independence
- testable business rules
โ๏ธ License
This package is open-source and licensed under the MIT License. See the LICENSE for details.
๐ฑ Contributing
Contributions are welcome and greatly appreciated!. See the CONTRIBUTING for details.
๐ Support
If you find this project useful, please consider giving it a star on GitHub!
It helps the project grow and motivates further development.