Skip to content

Constructing Types

Daniel Carbone edited this page Apr 2, 2026 · 6 revisions

Constructing Types

FHIR Resources, Elements, and Primitives are all located under each version's Types directory within the Versions namespace. See Type System for a deeper look at the type hierarchy and interfaces.

Directory Layout

Versions
├── DSTU1
│   └── Types
├── DSTU2
│   └── Types
├── R4
│   └── Types
├── R4B
│   └── Types
├── R5
│   └── Types
└── STU3
    └── Types

Each version's Types directory contains all Resource, Element, and Primitive classes for that version.

Type Hierarchy

Types are organized into a hierarchy based on their FHIR inheritance path. This changes, sometimes drastically, between FHIR versions, so you must be careful when working with multiple versions at the same time.

Type Constructors

Each type's __construct method contains a parameter for every property of that type, including all inherited parent properties.

As an example, here is the constructor for the root R4 Resource Type:

<?php

class FHIRResource implements ResourceTypeInterface, CommentContainerInterface
{
    /* ... */
    public function __construct(null|string|FHIRIdPrimitive|FHIRId $id = null,
                                null|FHIRMeta $meta = null,
                                null|string|FHIRUriPrimitive|FHIRUri $implicitRules = null,
                                null|string|FHIRCodePrimitive|FHIRCode $language = null,
                                null|iterable $fhirComments = null) {
        /* .. */
    }
    /* ... */
}

The parameters id, meta, implicitRules, language, and fhirComments are all properties of the FHIRResource type. Any child of this type will also have these parameters in its constructor.

Here is the constructor for the R4 DomainResource Type:

<?php

class FHIRDomainResource extends FHIRResource
{
    /* ... */
    public function __construct(null|string|FHIRIdPrimitive|FHIRId $id = null,
                                null|FHIRMeta $meta = null,
                                null|string|FHIRUriPrimitive|FHIRUri $implicitRules = null,
                                null|string|FHIRCodePrimitive|FHIRCode $language = null,
                                null|FHIRNarrative $text = null,
                                null|iterable $contained = null,
                                null|iterable $extension = null,
                                null|iterable $modifierExtension = null,
                                null|iterable $fhirComments = null)
    {
        parent::__construct(id: $id,
                            meta: $meta,
                            implicitRules: $implicitRules,
                            language: $language,
                            fhirComments: $fhirComments);
        /* ... */
    }
    /* ... */
}

As you can see, DomainResource extends Resource and its constructor inherits all parent parameters. Each type's constructor only handles its own (class-local) properties — inherited properties are passed up to the parent constructor.

Type Class Initialization

Because constructor parameters are cumulative, Resource types in particular can have constructors with dozens of parameters.

Bad — Positional Arguments

Take the R4 Patient Type, for example. Together with its local properties and all inherited properties, the Patient type has a constructor with 25 parameters!

Say you wanted to construct a simple Patient with an ID, a Language code, and a singular Name:

<?php

use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRElement\FHIRHumanName;
use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRResource\FHIRDomainResource\FHIRPatient;

$patient = new FHIRPatient(
    'patient-1',                            // id
    null,                                   // meta
    null,                                   // implicitRules
    'en-us',                                // language
    null,                                   // text
    null,                                   // contained
    null,                                   // extension
    null,                                   // modifierExtension
    null,                                   // identifier
    null,                                   // active
    [ new FHIRHumanName(given: ['Real'], family: 'Human') ], // name
);

That's awful, and no fun for anyone.

Good — Named Arguments

The same thing with named arguments:

<?php

use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRElement\FHIRHumanName;
use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRResource\FHIRDomainResource\FHIRPatient;

$patient = new FHIRPatient(
    id: 'patient-1',
    language: 'en-us',
    name: [ new FHIRHumanName(given: ['Real'], family: 'Human') ],
);

Much better! Named parameters let you target exactly the fields you want, without needing to fuss with all the intermediary null arguments.

Flexible Input Types

Constructor parameters accept multiple input types for convenience. For example, the id parameter on FHIRResource accepts:

  • string — a plain string value
  • FHIRIdPrimitive — the raw primitive type
  • FHIRId — the element wrapper type
  • null — leave unset

Similarly, collection fields (like name on Patient) accept iterable, so you can pass arrays or any iterable.

Building Complex Types

You can nest type construction as deeply as needed:

<?php

use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRElement\FHIRAddress;
use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRElement\FHIRContactPoint;
use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRElement\FHIRHumanName;
use DCarbone\PHPFHIRGenerated\Versions\R4\Types\FHIRResource\FHIRDomainResource\FHIRPatient;

$patient = new FHIRPatient(
    id: 'patient-1',
    name: [
        new FHIRHumanName(
            given: ['John', 'Michael'],
            family: 'Doe',
            prefix: ['Mr.'],
        ),
    ],
    telecom: [
        new FHIRContactPoint(
            system: 'phone',
            value: '+1-555-0100',
            use: 'home',
        ),
    ],
    address: [
        new FHIRAddress(
            line: ['123 Main St'],
            city: 'Springfield',
            state: 'IL',
            postalCode: '62704',
            country: 'US',
        ),
    ],
);

Clone this wiki locally