All notable changes to this project will be documented in this file.
enum()onFieldValidatornow accepts PHPUnitEnum(non-backed enums): the value must be an instance of the enum or a string equal to one of the case names;BackedEnumbehavior is unchanged (int or string backed values viatryFrom())
BoolValidator::coerce()no longer string-casts non-scalar values (arrays triggeredE_WARNING, objects without__toStringthrewError); non-scalars are passed through to type validation, which raisesValidationExceptionas for other invalid typescoerceAll()no longer callscoerce()on schema field validators in place (which leaked coercion to every other schema reusing the sameFieldValidatorinstance);coerceAll()now replaces each field with a clone that has coercion enabledcoerceAll()is now recursive: nestedAssociativeValidator,ObjectValidator, andArrayValidator(with item validators) all propagate coercion to their children; previously only top-level schema fields were coercedFieldValidator::__clone()skipsClosure::bindTo()for static closures (for example fromin()), avoiding PHP warnings when cloning such validators; pipeline steps now carry abindableflag set at insertion time so cloning no longer needsReflectionFunctionsatisfies(),satisfiesAll(),satisfiesAny(),satisfiesNone(), andArrayValidator::contains()now clone anyFieldValidatoroperand at capture time and rebuild those operands when the outer validator is cloned, so later mutations or clone-local pipeline state do not leak across validator instancesFieldValidator::tryValidate()now resets transient type-tracking before and after every validation run, so validators that usetransform()/pipe()remain repeatable across multiple calls and clones do not inherit stale runtime statedefault()no longer deep-copies object values; object defaults are returned as-is (shared by handle). UsedefaultUsing()when each validation run needs a fresh object instanceBase64Variant::UrlSafenow strictly validates URL-safe characters (-_) only; previously it was identical toBase64Variant::Any(accepted both standard and URL-safe)
defaultUsing(callable $factory)onFieldValidator: invokes the factory whenever validation resolves to null, providing a fresh default per validation run; intended for mutable domain objects or other defaults that should not be shared across validations or clonespassthrough()onAssociativeValidatorandObjectValidator: copy undeclared keys or public properties from the input to the validated output without validating them; declared schema fields are still validated; values already written from the schema (includingoutputKeytargets) are not overwritten by passthrough
uniqueField(string $fieldName, ?string $message = null)onArrayValidatorfor cross-item uniqueness validation of a nested field; convenience wrapper aroundsatisfies()that produces field-level error paths by structuring errors as[index => [fieldName => [message]]]; all members of a duplicate group receive errors (e.g., bothsymlinks.0.destinationandsymlinks.2.destination); skips items where the field is null or missing; works with both associative arrays and objects; uses strict comparison viaserialize()to distinguish types
- CRITICAL BUG: Fixed
default()andrequired()interaction --required()was rejecting null values beforedefault()had a chance to provide a fallback- Issue: Chaining
->default($value)->required()always threw "Value is required" for null inputs becauserequiredchecked for null beforedefaultwas applied - Root Cause:
tryValidate()had a scattered, multi-branch architecture withdefaultandrequiredchecks duplicated across 5+ locations (early returns, pre-pipeline, mid-loop, post-loop), making the interaction order unpredictable - Fix: Simplified
tryValidate()to a clean linear 5-step flow: coerce, type check, pipeline, default, required - Impact:
default()andrequired()now work cooperatively --default()is the last-resort fallback for null,required()only fails if the value is still null after default - Real-World Benefit: Enables patterns like
->pipe(fn($x) => null)->default($fallback)->required()where a pipeline step intentionally nullifies a value anddefault()catches it beforerequired()enforces presence
- Issue: Chaining
- Simplified
tryValidate()pipeline architecture -- reduced from 67 lines with 5+ branch points to 33 lines with a linear flow- Removed 2 duplicated early returns for null + no-pipeline + not-required
- Removed mid-loop
default()andrequired()checks (were duplicating post-loop logic) default()now applies in exactly one place: after the pipeline, as the last-resort fallbackrequired()now checks in exactly one place: at the very end, after default has had its chance- Pipeline always runs fully without mid-step bailouts
- Validation flow is now: coerce -> type check -> pipeline -> default -> required
enum(class-string<\BackedEnum> $enumClass, ?string $message = null)onFieldValidatorfor PHP BackedEnum validation; restricts the value to one of the enum's backed cases (int or string); available on all validator types; useenum(StatusEnum::class)instead ofin(array_map(fn($e) => $e->value, StatusEnum::cases()))const(mixed $value, ?string $message = null)onFieldValidatorfor single-value validation; restricts the value to exactly one allowed constant using strict comparison (===); available on all validator types; useconst('active')instead ofin(['active'])for clearer intentoutputKey(string $key)onFieldValidatorfor schema fields: output validated values under a different key than the input field (e.g. inputservice_id-> outputserviceafter transform); works withValidator::isAssociative()andValidator::isObject()- GitHub Actions CI: lint, platform-check, static analysis, tests on PHP 8.3
- Applied Mago formatting and new linter rules across the codebase (readable-literal, no-isset); updated mago.toml (print-width 120, preserve-breaking-* options)
- Renamed
composer fixscript tocomposer formatfor Mago formatting - Mago now a dev dependency (carthage-software/mago) instead of global installation
- Added
config.platform.php: "8.3.0"so dependency resolution targets PHP 8.3;composer update/installwill not add packages requiring PHP above 8.3 - Added
composer platform-checkscript to verify platform requirements
- BREAKING:
transform()now skipsnullvalues by default (was executing on null)- Rationale: Most type conversions don't need null handling, making this safer and more efficient by default
- Migration: Use
transform($fn, skipNull: false)if you need to process null values (e.g.,transform(fn($v) => $v ?? 'fallback', skipNull: false)) - Impact: Existing code that relied on
transform()executing on null will need to explicitly setskipNull: false - Real-World Benefit: Prevents errors when null values reach type conversions like
DateTime::createFromFormat(),explode(),strlen(), etc.
notEmpty()convenience method forStringValidatorandArrayValidatorto reject empty strings/arraysbetween()shorthand for string length and numeric range constraints with unified error messagesin()alias foroneOf()on primitive validators for clearer allowed-value validationtransform()method now accepts optional$skipNullparameter (default:true) to configure null handling
oneOf()in favor ofin()(alias retained for backward compatibility)
- Clarified fail-fast behavior per field and schema-level error aggregation in guides and examples
- Updated transformation documentation to reflect new null handling behavior
- CRITICAL BUG: Fixed array validator error handling to preserve array indices in flattened error messages
- Issue: Array item validation errors lost array index information, showing paths like
symlinks.destinationinstead ofsymlinks.0.destination - Root Cause:
ArrayValidatorusedvalidate()which threw immediately on first error, losing index context and preventing error collection - Fix: Changed to use
tryValidate()for all items, collecting errors with proper indexing (similar toAssociativeValidatorbehavior) - Impact: Flattened error messages now correctly identify which array item has validation errors (e.g.,
symlinks.0.destination,symlinks.2.destination) - Behavior: All array item errors are now collected (not just the first), and indices are preserved in error paths
- Real-World Benefit: API error responses and form validation can now accurately pinpoint which array element failed validation
- Issue: Array item validation errors lost array index information, showing paths like
- CRITICAL BUG: Fixed null handling for transformation methods to match documented behavior
- Issue:
pipe()transformations (liketrim()) were executing onnullvalues, causingTypeErrorexceptions - Root Cause: All transformations were executing on null, but
pipe()transformations are type-preserving and expect specific types - Fix: Implemented
skipNullflag in pipeline structure -pipe()now skips null (type-preserving, expects specific type),transform()executes on null (can handle null and change types) - Impact:
pipe()transformations correctly skip null values, preventing errors with functions liketrim()that don't accept null - Behavior:
transform()continues to execute on null as designed (can transform null to other values/types) - Clone Support: Updated
__clone()method to preserveskipNullflag when cloning validators - Real-World Benefit: Form validation with optional fields using
pipe(trim(...))now works correctly without errors
- Issue:
- Clarified null handling differences between
pipe()andtransform()in transformation guidance.
getFlattenedErrors()method onValidationExceptionreturning a flattened list of errors suitable for API consumption. Each error entry containspath(field path with'_root'for root-level errors) andmessage(error message). Supports nested structures, array items, and maintains consistent path notation.ValidationException::flattenErrors()static method for flattening errors fromtryValidate()results without needing to catch exceptions. Returns empty array when passednull.
- Numeric comparison helpers (
gt,gte,lt,lte), non-negative/non-positive validators, andclampToRange(min, max)transformation for numeric validators. - String format validators:
hostname(),time(),base64(),hex(),domain(), andregex()alias method forpattern()onStringValidator. port()method forIntValidatorto validate port numbers (1-65535) as numeric constraints.- Enum-based variant flags:
IpVersionenum for IP address validation,Base64Variantenum for Base64 validation, andUuidVariantenum for UUID validation. - UUID version 7 support in
UuidVariantenum (Unix timestamp-based, sortable). - Array length constraints:
minItems()andmaxItems()methods forArrayValidatorto validate array size. - Array contains validation:
contains()method forArrayValidatorsupporting both specific value matching and validator-based item matching. - Comprehensive documentation clarifying library philosophy: focus on core validation principles over exhaustive validator coverage, with external libraries encouraged for advanced/specialized validators.
- BREAKING: Refactored
ip()method to useIpVersionenum flag instead of separateipv4()/ipv6()methods. Useip(IpVersion::IPv4)orip(IpVersion::IPv6)for version-specific validation. Enum flag comes first, message parameter last. - BREAKING: Refactored
base64()method to useBase64Variantenum flag. Usebase64(Base64Variant::UrlSafe)for URL-safe Base64 validation orbase64(Base64Variant::Any)to accept both variants. Enum flag comes first, message parameter last. - BREAKING: Refactored
uuid()method to useUuidVariantenum flag. Useuuid(UuidVariant::V1)throughuuid(UuidVariant::V7)for version-specific validation, oruuid(UuidVariant::Any)(default) to accept all versions (1-7). Enum flag comes first, message parameter last. - Enhanced documentation to clarify library philosophy: primary focus on core validation principles rather than implementing every possible validator. External libraries are strongly encouraged for advanced, specialized, or frequently-evolving validators.
- Added
declare(strict_types=1);across the codebase for stricter type enforcement and clearer errors. - Replaced php-cs-fixer with Mago for linting/formatting; scripts now map
composer lint/composer fixto Mago.
- Validator cloning: Added
clone()support to all validators for safe reuse of prebuilt pipelines without shared state. Pipelines are rebound to the cloned instance and nested schemas/item validators deep-clone to avoid cross-contamination between validators.
- Migrated all runtime classes to the
Lemmon\Validatornamespace and aligned documentation/examples with the new structure.
- Type-Safe Pipeline Architecture: Enhanced internal architecture with
PipelineTypeenum for improved developer experience- IDE Autocomplete Support:
PipelineType::VALIDATIONandPipelineType::TRANSFORMATIONwith full IDE integration - Refactoring Safety: No more magic strings - IDE handles all references automatically during refactoring
- Self-Documenting Code: Clear intent with documented enum cases explaining validation vs transformation behavior
- Future Extensibility: Easy to add new pipeline types (e.g.,
CONDITIONAL,ASYNC) with type safety - Zero Runtime Cost: Enums compile to same string values with no performance impact
- Perfect Static Analysis: PHPStan level max compliance with proper type annotations
- IDE Autocomplete Support:
- Smart Null Handling: Revolutionary null handling system that makes validation intuitive and order-independent
- Intelligent Null Processing: Validations automatically skip
nullvalues unless field is marked asrequired() - Order Independence:
->email()->required()and->required()->email()both work identically withnullinputs - Transformation Consistency: Transformations (
pipe(),transform(),nullifyEmpty()) always execute, even onnullvalues - Global Required Flag:
required()works as a global flag (likecoerce()), not a pipeline step - Smart Default Application: Default values applied after pipeline execution if final result is
null - Real-World Benefit: Eliminates confusing execution order dependencies - write validation chains naturally
- Backward Compatible: All existing code works unchanged with the full suite
- Intelligent Null Processing: Validations automatically skip
- Unified Pipeline Architecture: Revolutionary single pipeline design that maintains conceptual clarity while optimizing execution
- Hybrid Execution Model: Pure validations (like
email(),minLength()) collect all errors for better UX, while transformations (likerequired(),pipe()) fail fast for correct behavior - Execution Order Guarantee: All methods execute in the exact order written in the fluent chain -
->email()->required()->pipe('trim')works exactly as expected - Conceptual Simplicity: From developer perspective, there's one pipeline where callbacks do whatever they need (validate, transform, or both)
- Performance Optimized: Error collection only where beneficial, fail-fast where appropriate
- Backward Compatible: All existing code works unchanged across the full suite
- Internal Architecture: Maintains separate
$validations(error collection) and$pipeline(transformations) arrays for optimal execution
- Hybrid Execution Model: Pure validations (like
- New
satisfies*API: Enhanced instance logical combinators for improved API consistency and flexibilitysatisfiesAny(array $validations, ?string $message = null)- Validates that value passes ANY of the provided validators or callablessatisfiesAll(array $validations, ?string $message = null)- Validates that value passes ALL of the provided validators or callablessatisfiesNone(array $validations, ?string $message = null)- Validates that value satisfies NONE of the provided validators or callables- Enhanced
satisfies()Method: Now acceptscallable|FieldValidatorinstances for maximum flexibility - Backward Compatibility: Deprecated
anyOf(),allOf(),not()instance methods maintained as aliases - API Clarity: Eliminates confusion between static
Validator::anyOf()and instance$validator->anyOf()methods - Updated test metrics to reflect expanded coverage
- Refactored
oneOf()toOneOfTrait: Improved type safety and execution order consistency- Type Safety:
oneOf()now only available on primitive validators (StringValidator,IntValidator,FloatValidator,BoolValidator) - Execution Order:
oneOf()now implemented as transformation, respecting fluent API chain position - Logical Consistency: Removed from complex types (
ArrayValidator,ObjectValidator) where it doesn't make semantic sense - Breaking Change:
ArrayValidatorandObjectValidatorno longer haveoneOf()method - Added comprehensive test coverage and removed invalid test cases
- Type Safety:
- Form-Safe Empty String Coercion: Enhanced ObjectValidator and AssociativeValidator coercion for better form handling
ObjectValidator::coerce(): Empty strings ('') now coerce to emptystdClassobjectsAssociativeValidator::coerce(): Empty strings ('') now coerce to empty arrays[]- Real-World Benefit: Form parameters like
?settings=now create empty structures instead of failing validation - Type Safety Maintained: Non-empty strings still fail validation as expected
- Added comprehensive test coverage
- Enhanced
required()Method: Added optional custom error message parameter for consistency with other validation methodsrequired(?string $message = null)- Custom error messages for required field validation- API Consistency: All validation methods now support optional custom error messages
- Better UX: Context-specific error messages for different forms and use cases
- Maintains backward compatibility with existing code
- Internal API Modernization: Complete migration from deprecated
addValidation()tosatisfies()throughout codebase- StringValidator: All 10 validation methods (
email(),url(),uuid(),ip(),minLength(),maxLength(),length(),pattern(),datetime(),date()) now usesatisfies()internally - NumericConstraintsTrait: All 5 constraint methods (
min(),max(),multipleOf(),positive(),negative()) now usesatisfies()internally - Static Methods:
Validator::anyOf(),Validator::allOf(),Validator::not()now use newsatisfies*API internally - Future-Proofing: All internal code ready for
addValidation()removal in v1.0.0 - Consistency: Single source of truth for custom validation logic across entire codebase
- Maintains perfect backward compatibility for users still using deprecated methods
- StringValidator: All 10 validation methods (
- CRITICAL BUG: Fixed execution order for
required()andnullifyEmpty()methods to respect fluent API contract- Issue:
Validator::isString()->pipe('trim')->nullifyEmpty()->required()->validate(' ')incorrectly passed validation - Root Cause:
required()andnullifyEmpty()executed before transformations, violating principle of least surprise - Fix: Moved both methods to transformation pipeline to respect their position in the fluent chain
- Impact: Fluent API now works exactly as written - transformations execute in the order they appear
- Breaking Change: Execution order now matches developer expectations (trim → nullifyEmpty → required)
- Real-World Benefit: Form validation with trimming and empty string handling now works correctly
- Issue:
- CRITICAL BUG: Fixed floating-point precision issue in
multipleOf()validation- Issue:
Validator::isFloat()->multipleOf(0.01)->validate(500.01)failed due to floating-point arithmetic precision - Root Cause:
fmod(500.01, 0.01)returned0.009999999999980497instead of0.0 - Fix: Implemented epsilon comparison (
1e-9tolerance) for floating-point remainder validation - Impact: Decimal multiples (currency, measurements) now validate correctly
- Added comprehensive test coverage for floating-point precision edge cases
- Issue:
- CRITICAL BUG: Fixed schema validation field inclusion behavior in ObjectValidator and AssociativeValidator
- Issue: Validators were incorrectly including ALL schema fields in results, even when not provided in input
- Fix: Now only includes fields that were actually provided in input OR have default values applied
- Impact: Results now accurately reflect validated data without unexpected properties
- Behavior: Required field validation still works correctly (missing required fields still fail)
- Added comprehensive test coverage to prevent regression
- Documentation: Added "Field Inclusion Behavior" section to Object Validation guide with clear examples
- Complete type-aware transformation system documentation - Added comprehensive coverage for
transform()andpipe()methods- Added "Data Transformations" section to Core Concepts guide with detailed type context switching explanation
- Added transformation examples to Basic Usage guide with clear usage guidelines
- Documented
filterEmpty()method for ArrayValidator with practical examples and real-world use cases - Added "Type-Specific Methods" section to API Reference with complete array method documentation
- Fixed API reference to match actual implementation (removed unimplemented boolean parameter methods)
- Updated ROADMAP to remove unimplemented enhanced methods and focus on existing features
- Complete
nullifyEmpty()documentation - Added comprehensive coverage across all guides and API reference- Added "Universal Methods" section to API Reference with detailed
nullifyEmpty()documentation - Added "Form-Safe String Handling" section to String Validation Guide with practical examples
- Added "Explicit Empty String Nullification" section to Numeric Validation Guide
- Added "Form-Safe Validation with nullifyEmpty()" section to Form Validation Examples
- Added "Empty String Nullification" section to Basic Usage Guide with fundamental patterns
- Updated README.md Quick Start example to showcase
nullifyEmpty()usage
- Added "Universal Methods" section to API Reference with detailed
- Fixed all dead links in documentation - Replaced 15 dead links with existing comprehensive guides
- Fixed missing API reference links across all documentation files
- Ensured all internal navigation works properly for seamless user experience
- Added development notice - Clear indication that the library is in active development with potential API changes
- CRITICAL BUG: Fixed ObjectValidator null property handling -
isset()was excluding null properties from result objects- ObjectValidator now correctly includes all validated properties in the result, even when they are null
- Maintains consistency with AssociativeValidator behavior
- Added comprehensive test coverage to prevent regression
- BREAKING CHANGE: Enhanced form safety for empty string coercion across all validators
IntValidator::coerce(): Empty strings ('') now convert tonullinstead of0FloatValidator::coerce(): Empty strings ('') now convert tonullinstead of0.0BoolValidator::coerce(): Empty strings ('') now convert tonullinstead of validation failure- Rationale: Prevents dangerous zero defaults in form fields (e.g., bank balances, quantities)
- Migration: Use explicit
->default(0)if you need zero defaults for empty form fields - Added comprehensive test coverage for new behavior
- New
satisfies()Method: Intuitive custom validation with optional error messages- Replaces verbose
addValidation()with natural language:->satisfies(fn($v) => $v > 0) - Optional error message parameter with sensible default: "Custom validation failed"
- Maintains backward compatibility with deprecated
addValidation()method - Added comprehensive test coverage
- Updated all documentation (65+ references) to use new method
- Replaces verbose
- BoolValidator Test Suite: Complete test coverage for boolean validation and coercion
- Tests for string boolean coercion (
'true','false','on','off','1','0') - Case-insensitive coercion support
- Empty string safety validation
- Tests for string boolean coercion (
- Developer Experience: Natural language validation with
satisfies()method reads like English - API Consistency: Optional error messages eliminate forced message requirements
- Documentation Quality: Comprehensive updates across all guides with practical examples
- Form Safety: Real-world protection against dangerous zero defaults in financial and quantity fields
- Enhanced Numeric Coercion:
IntValidatorandFloatValidatorcoercion improvements for form handling⚠️ SUPERSEDED: This behavior was changed in the next release for safety reasons- See "Unreleased" section for current empty string coercion behavior
- Array Filtering with Auto-Reindexing: New
filterEmpty()method forArrayValidator- Removes empty strings (
'') andnullvalues while preserving valid falsy values (0,false,[]) - Automatically reindexes arrays to maintain indexed array structure (0, 1, 2, 3...)
- Works seamlessly with item validators for comprehensive array cleanup
- Removes empty strings (
- Type-Aware Transformation System: Revolutionary transformation infrastructure with intelligent type handling
transform(callable $transformer)- Type-flexible transformations that can change data typespipe(callable ...$transformers)- Type-preserving transformations that maintain current type context- Dynamic Type Context: Automatically tracks and switches type context during transformation chains
- Smart Array Coercion:
pipe()operations on arrays automatically reindex to maintain structure - Associative Key Preservation: AssociativeValidator preserves keys during
pipe()operations - Enables complex multi-type transformation chains (Array → String → Int) with intuitive syntax
- Form Data Handling: Enhanced coercion makes form validation significantly more practical and intuitive
- Array Data Integrity:
filterEmpty()maintains ArrayValidator's contract of returning properly indexed arrays - Extensibility: Universal transformation methods enable unlimited flexibility with external library integration
- Test Coverage: Expanded coverage across numeric, array, and type-aware transformation validators
- Static Logical Combinators: New static factory methods for advanced validation logic
Validator::anyOf(array $validators)- Creates validator that passes if ANY validator passes (perfect for mixed-type validation)Validator::allOf(array $validators)- Creates validator that passes if ALL validators pass (ideal for combining constraints)Validator::not(FieldValidator $validator)- Creates validator that passes if the provided validator does NOT pass (exclusion logic)
- Enhanced Mixed-Type Support: Clean syntax for validating arrays with mixed item types
- Comprehensive Documentation: Complete documentation restructure with focused guides, API reference, and practical examples
- Getting Started guides (Installation, Basic Usage, Core Concepts)
- Validation Guides (String, Numeric, Array, Object, Custom, Error Handling)
- API Reference with complete method documentation including new static combinators
- Real-world Examples (Form validation, API validation, E-commerce)
- Enhanced README: Concise overview with quick start examples and organized navigation
- Comprehensive Test Suite: Expanded coverage for static logical combinators
- API Consistency: Static logical combinators provide cleaner syntax than instance-only methods
- Mixed-Type Validation: Simplified array validation with
Validator::anyOf()for mixed types - Documentation Coverage: All new methods fully documented with practical examples
- Type Safety: Static combinators work with any data type while maintaining type safety
- Complete String Validation Suite: Added comprehensive string format validators:
url()- Validates URLs with support for various protocolsuuid()- Validates UUID strings (all versions)ip()- Validates IPv4 and IPv6 addressesminLength(),maxLength(),length()- String length constraintspattern()- Regular expression pattern matchingdatetime(),date()- Date and datetime format validation
- FloatValidator: New dedicated validator for floating-point numbers with full constraint support
- NumericConstraintsTrait: Shared trait for numeric validations eliminating code duplication between
IntValidatorandFloatValidator - Enhanced IntValidator: Added numeric constraints (
min(),max(),multipleOf(),positive(),negative()) - Logical Combinators: Advanced validation logic with
allOf(),anyOf(), andnot()methods - Comprehensive Error Collection: Validators now collect all validation errors instead of stopping at the first failure
- Enhanced Validation Context: Custom validators receive
(value, key, input)parameters for context-aware validation
- BREAKING: Renamed
NumberValidatortoFloatValidatorfor clearer semantics - BREAKING: Renamed
Validator::isNumber()toValidator::isFloat()for consistency with PHP types - Enhanced
addValidation()method to support context-aware custom validation functions - Improved error messages and validation feedback throughout the library
- Refactored numeric constraint methods to use shared
NumericConstraintsTrait
- Test Organization: Split monolithic test suite into focused test files:
AssociativeValidatorTest.php- Associative array validationObjectValidatorTest.php- stdClass object validationArrayValidatorTest.php- Plain array validationStringValidatorTest.php- String validation and formatsIntValidatorTest.php- Integer validationFloatValidatorTest.php- Float validationFieldValidatorTest.php- Base validator functionalityNumericConstraintsTraitTest.php- Trait-specific tests
- Code Quality: Achieved 100% PHPStan compliance and PHP-CS-Fixer standards
- Performance: Optimized validation logic and eliminated code duplication
ObjectValidatorfor validatingstdClassobjects, created withValidator::isObject().- Coercion support for
ObjectValidatorto convert associative arrays intostdClassobjects. - Coercion support for
AssociativeValidatorto convertstdClassobjects into associative arrays.
- BREAKING: Renamed
SchemaValidatortoAssociativeValidatorfor better API consistency. - The factory method
Validator::isAssociative()now returns anAssociativeValidatorinstance. - Improved error message for associative array type validation to be more specific.
- Changed the type hint on
FieldValidator::tryValidate()tomixedto correctly accept both array and object payloads as context.
- Initial release of the
lemmon/validatorpackage.