Skip to content

Constructing Types

Daniel Carbone edited this page Feb 8, 2025 · 5 revisions

FHIR Resources, Elements, and Primitives are all located under the src/DCarbone/PHPFHIRGenerated/Types directory. Each of the versions generated by php-fhir are further separated into subdirectories carrying their name, as such:

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

Each of these version directories contains a directory named Types, as you can see above. This is where all Resource, Element, and Primitive classes exist for that version.

Type Hierarchy

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

Type Constructors

Each type's __construct method contains a parameter to set every property of that type, including all 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, the DomainResource type extends the Resource type, and its constructor therefore inherits all parameters from its parent type. Each type's constructor only handles class-local properties, however. All properties inherited from parents are passed to the parent constructor.

Type Class Initialization

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

Bad - Positional Arguments

Let's take the R4 Patient Type, for example. It extends DomainResource, which in turn extends Resource. Together with its local 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 with positional arguments:

<?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

Let's try the same thing, but this time 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 to construct, without needing to fuss with all the intermediary parameters.