All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
- [Docs] Removed the stale "single-element repeating fields" XML limitation note from the serialization guide; single-value repeating fields (e.g. a
HumanNamewith onegiven) already round-trip correctly through XML, and a regression test now guards this - [Docs] Corrected the Questionnaire validation guide:
enableWhenExpression(SDC + Kanta variants) andregexconstraints are now documented as covered, the implementation-rules table lists the enforced constraint/value-domain/quantityerrorrules, and the conformance-coverage section reflects that all 78 eligible R4 cases are seeded and asserted (only SDCanswerExpression/calculatedExpressionand R5answerConstraintremain uncovered)
0.4.0 - 2026-06-12
- [Validation] New
ardenexal/fhir-validationcomponent:FHIRValidationServicevalidates resources against profiles and reports results as a FHIROperationOutcome - [Validation] Constraint validators for profile constraints, fixed values, pattern values, slices, value-set bindings (required/extensible/preferred +
maxValueSet),mustSupport, obligations, target profiles, and FHIRPath invariants - [Validation] Terminology validation: pluggable terminology client (
NullFHIRTerminologyClientand HTTP client with$validate-codePOST support), strict mode, and PSR-6 caching of terminology results with configurable TTL - [Validation] Questionnaire and QuestionnaireResponse validation:
FHIRQuestionnaireValidatorandFHIRDerivedQuestionnaireValidatorcovering min/max occurs,enableWhenexpressions, status/effectivePeriod, and preferred terminology server resolution; seeded with the brianpos and ardenexal R4/R4B/R5 conformance corpora - [Validation]
FHIRTemporalRangeandFHIRQuantityRangeconstraints and validators; quantity bounds are compared only when the instance and bound share the same unit (system+code), with cross-unit bounds surfaced as warnings (no UCUM conversion) - [Validation] Extension context validation via
FHIRExtensionContextandFHIRContextInvariantattributes, including recursive/nested context evaluation through FHIRPath - [Metadata]
ardenexal/fhir-metadatais now standalone-installable;FHIRIGTypeRegistryand its factory moved here from Serialization - [Serialization] All primitive types now implement
Stringable - [Bundle]
fhir.validation, terminology cache, and message-override configuration keys
- [Serialization] FHIR primitive extension arrays on array-typed fields now serialize and deserialize correctly in complex and backbone normalizers (spec-compliant round-trip)
- [Serialization] XML deserialization of primitive-with-extension elements
- [Serialization] Consistent extension-URL resolution across normalizers
- [Validation] Temporal-range (
minValue/maxValue) constraints are now enforced on real model objects instead of silently skippingStringableprimitive wrappers - [FHIRPath] Quantity add/subtract no longer fabricates wrong-unit results; quantity divide-by-zero now returns an empty collection instead of throwing
DivisionByZeroError - [Validation] Guard uninitialized typed properties in
FHIRValidationServiceto prevent crashes on constructor-bypassed (deserialized) objects - [Metadata]
FHIRExtensionsTraitlookup helpers no longer error on uninitializedextensionproperties
- [Core] BREAKING: The default FHIR version changed from R4B to R4 across all runtime and codegen entry points (
FHIRSerializationService::createDefault()/createWithIG(), thefhir.default_versionconfig node,fhir:generatedefault IG packages, and theFHIRPrimitive/FHIRComplexType/FHIRBackboneElementattribute defaults). PassFhirVersion::R4B(ordefault_version: 'R4B') explicitly to retain the previous behaviour - [Models] BREAKING: Abstract resource base classes are no longer generated with a doubled
Resourcesuffix; they now use anAbstractprefix:ResourceResource→AbstractResource,DomainResourceResource→AbstractDomainResource, and (R5 only)CanonicalResourceResource→AbstractCanonicalResource,MetadataResourceResource→AbstractMetadataResource. Concrete resource classes are unchanged (e.g.PatientResource) - [Serialization] Normalizers split into
Normalizer\Json\*andNormalizer\Xml\*namespaces - [Validation] Conformance semantics aligned with the dotnet/brianpos reference for partial-date bounds, quantity bounds, and draft/in-progress leniency (ADR-008)
- [Docs] Rewrote the Serialization and FHIRBundle component guides to match the real public API (
FHIRSerializationService::createDefault(),serializeToJson/deserializeFromJson, immutableFHIRSerializationContext)
- [Metadata] PHP floor raised to
>=8.3;symfony/finderdependency declared - [CI] ParaTest-based parallel test execution; consolidated unit and integration suites into a single parallelized matrix; PHPStan analysis of generated models added to CI
- [CI] Codecov configuration and phpbench baseline detection fixes
0.3.1 - 2026-05-07
- Fix failing serialization unit tests
- Update component version constraints to
^0.3
0.3.0 - 2026-05-06
- [IG Generation]
fhir:generate-igcommand for generating typed PHP classes from FHIR Implementation Guide StructureDefinitions - [IG Generation]
FHIRExtensionGeneratorfor simple (single value type) and complex (sub-extension slices) typed extension classes - [IG Generation]
FHIRProfileGeneratorfor profile subclasses with multi-level inheritance support - [IG Generation]
FHIRExtensionDefinitionandFHIRProfilemetadata attributes for runtime introspection - [IG Generation] Transitive IG dependency package auto-loading into
BuilderContextfor cross-package type resolution - [IG Generation] FHIR R4B/R5 extension classes and FHIR R5 enums for various value sets
- [IG Generation] Slice discriminator support
- [Serialization]
FHIRIGTypeRegistryfor URL-to-class mapping of typed IG extension and profile subclasses - [Serialization]
FHIRIGRegistryCompilerPassto scan the IG output directory and wire up the registry at compile time - [Serialization]
FHIRComplexExtensionInterfacewithfromSubExtensions()factory for complex extension deserialization - [Serialization]
PropertyMetadataProvidernow walks the full class hierarchy so typed extension subclasses inheritFhirPropertymetadata from parent classes - [Bundle]
fhir.ig.*configuration keys (namespace,output_directory,offline,packages) inconfig/packages/fhir.yaml - [Bundle] FHIR metadata cache warmer with configurable
enable_cache_warmeroption - [Metadata]
FHIRExtensionInterfaceproviding a commongetExtensionUrl()typing point across R4/R4B/R5 - [Metadata]
FHIRExtensionsTraitwith lookup helpers:findExtension,findExtensions,hasExtension,findExtensionByUrl,findExtensionsByUrl - [FHIRPath] Benchmarks for FHIRPath evaluation and parsing
- [Infrastructure] Deployment workflow and documentation for the demo app
- [Serialization] Null checks and type casting added for primitives
- [Serialization] Extensions and normalizers updated for versioning and deprecation handling
- [Docs]
fhir:generate-igcommand, IG bundle configuration, and component guides documented in README
- [IG Generation] Base constraint profiles (vitalsigns, bp, bodyheight, etc.) now generated so IG profiles that extend them resolve correctly
- [IG Generation] Slice parameter names conflicting with parent
Extensionproperties now suffixed withSliceto avoid PHP property invariance compile errors - [Serialization] Base extensions registered in
FHIRIGTypeRegistryso deserializer uses typed subclasses instead of falling back toExtension - [Serialization] Complex extension deserialization now uses
fromSubExtensions()to correctly populate typed promoted properties - [Serialization] PHPStan and PHPUnit notice issues in serialization layer
- [Infrastructure] Dockerfile updated with zip extension for Composer dist downloads
- [Infrastructure] Demo
composer.lockconstrained to PHP 8.3 compatible packages - [FHIRPath] PHPDoc type hints improved in
FHIRPathEvaluator