aegisora / any-of-rule
Any Of Rule provides a simple, rule-based logical OR validation implementation for the Aegisora ecosystem.
Requires
- php: >=7.4
- aegisora/rule-contract: ^1.1
Requires (Dev)
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^9.6
- squizlabs/php_codesniffer: ^4.0
README
Any Of Rule provides a simple, rule-based logical OR validation implementation for the Aegisora ecosystem.
It is built on top of aegisora/rule-contract and follows its strict validation architecture, ensuring consistent and predictable behavior across applications.
This rule is useful whenever a value is acceptable if it satisfies at least one of several alternative rules โ for example, accepting either an email or a phone number, matching one of several allowed formats, or passing any one of a set of business constraints.
๐ Table of Contents
- Features
- Installation
- Core Concept
- Basic Usage
- Valid vs Invalid
- Validation Result
- Guardian Usage
- Real-World Examples
- Factory Methods
- Architecture
- License
- Contributing
- Support
โจ Features
- ๐น Lightweight and dependency-free except
aegisora/rule-contract - ๐น Validates that a value satisfies at least one of several rules (logical OR)
- ๐น Short-circuits on the first rule that passes
- ๐น Accepts a
RuleContextCollectionof(rule, context)pairs - ๐น Rejects a non-collection or an empty collection as an invalid context
- ๐น Fully compatible with Aegisora validation pipeline
- ๐น Strict
ContextโResultvalidation flow - ๐น No raw booleans โ only structured results
- ๐น Safe execution via base
Ruleabstraction - ๐น Simple factory API (create)
- ๐น Ready to use out of the box
๐ฆ Installation
composer require aegisora/any-of-rule
๐ Core Concept
This package implements a single validation rule:
- accepts a
RuleContextCollectionviaContext - runs each inner rule against its own context
- passes as soon as any inner rule reports a valid result
- returns a standardized
Result
Under the hood it wraps the common boilerplate:
foreach ($ruleContextCollection as $ruleContext) { if ($ruleContext->getRule()->validate($ruleContext->getContext())->isValid()) { // at least one rule passed } }
into a reusable rule that reports its outcome through a Result object instead of a raw boolean.
๐๏ธ Basic Usage
use Aegisora\RuleContract\Models\Context; use Aegisora\RuleContract\Models\RuleContext; use Aegisora\RuleContract\Models\RuleContextCollection; use Aegisora\Rules\AnyOfRule; $result = AnyOfRule::create()->validate( Context::create( RuleContextCollection::create( RuleContext::create($emailRule, Context::create($value)), RuleContext::create($phoneRule, Context::create($value)) ) ) ); if ($result->isValid()) { // value satisfied at least one rule } else { // value satisfied none of the rules }
โ Valid vs Invalid
The rule passes when at least one inner rule is valid and fails only when every inner rule is invalid.
Valid
$rule = AnyOfRule::create(); // passes โ the first rule is valid $rule->validate( Context::create( RuleContextCollection::create( RuleContext::create($validRule, Context::create($value)) ) ) ); // passes โ at least one rule in the collection is valid $rule->validate( Context::create( RuleContextCollection::create( RuleContext::create($invalidRule, Context::create($value)), RuleContext::create($validRule, Context::create($value)) ) ) );
Invalid
$rule = AnyOfRule::create(); // fails โ every rule in the collection is invalid $rule->validate( Context::create( RuleContextCollection::create( RuleContext::create($invalidRule, Context::create($value)), RuleContext::create($invalidRule, Context::create($value)) ) ) );
๐งช Validation Result
If at least one inner rule is valid, the rule returns a valid result.
$result->isValid(); // true
If every inner rule is invalid, the rule returns an invalid result.
$result->isValid(); // false $result->getFailedRuleCode(); // any_of_rule
If the context value is not a RuleContextCollection, or the collection is empty, the rule throws:
Aegisora\RuleContract\Exceptions\InvalidRuleContextException
๐ Guardian Usage
This rule can be used together with aegisora/guardian to build fluent validation pipelines.
use Aegisora\Guardian\Guardian; use Aegisora\RuleContract\Models\Context; use Aegisora\RuleContract\Models\RuleContext; use Aegisora\RuleContract\Models\RuleContextCollection; use Aegisora\Rules\AnyOfRule; use App\Exceptions\InvalidValueException; $guardian = new Guardian(); $guardian ->that( RuleContextCollection::create( RuleContext::create($emailRule, Context::create($value)), RuleContext::create($phoneRule, Context::create($value)) ) ) ->must(AnyOfRule::create(), new InvalidValueException()) ->validate();
If none of the rules pass, Guardian throws the provided domain exception.
๐งญ Real-World Examples
Any Of Rule is useful whenever a value has several acceptable alternatives.
Examples
Contact:
accept the value if it is a valid email OR a valid phone number
Identifiers:
accept either a UUID OR a numeric id
Formats:
allow a date in one of several supported formats
Access:
grant access if any one of several permission rules is satisfied
๐งฉ Factory Methods
AnyOfRule::create();
- no arguments โ creates a new rule instance
AnyOfRule::create()->validate($context);
$contextโContextwrapping theRuleContextCollectionto validate
๐๏ธ Architecture
This package relies on aegisora/rule-contract.
Flow:
validate()is calledContextis passed in- The
RuleContextCollectionis extracted from context (non-collections and empty collections raiseInvalidRuleContextException) - Each
RuleContextis validated against its ownContext - The rule passes on the first valid result and fails if none are valid
Resultis returned โ valid on success, invalid with theany_of_rulecode on failure
All logic is safely handled by Rule contract.
โ๏ธ 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.