Giter Club home page Giter Club logo

php-fhir's Introduction

php-fhir

Tools for creating PHP classes from the HL7 FHIR Specification

If you're looking to use the classes generated by this library, you may want the php-fhir-generated repo instead.

Index

  1. Install as Standalone Generator
  2. Install as Library
  3. Version Table
  4. Basic Usage
  5. Serializatoin
  6. Testing

Install as Standalone Generator

If you wish to use this package as a standalone generator:

  1. Check out the desired branch or tag
  2. Execute composer install from root of project directory
  3. Execute ./bin/generate.sh
  4. Answer all prompts
    • If no custom configuration file is defined, definitions will be downloaded to ./input and classes will be generated under ./output
    • You can execute ./bin/generate.sh --help for details on how to utilize this script
    • You can configure various aspects of this script by altering the values in ./bin/config.php

This script will download configured major versions of FHIR into the input folder and generate classes for every version in the output folder.

Install as Library

If you wish to use the generator as part of a project, you can include it as a composer dependency:

composer require dcarbone/php-fhir

From there, you can reference the Example block for a quick example on how to configure and execute the generator.

Version Table

PHPFHIR Version PHP Versions FHIR Versions
v2 5.4-7.4 DSTU1, DSTU2, STU3, R4 (<v4.3.0)
v3 8.1+ DSTU1, DSTU2, STU3, R4, R5

Basic Usage

The first step is to determine the version of the FHIR spec your implementation supports. Once done, download the appropriate class definition XSDs from http://hl7.org/fhir/directory.html.

Uncompress the XSD's and place them in a directory that is readable by PHP's runtime user.

Next comes the fun:

Class Generation

The class generator utility included with this library is designed to parse the XSD's provided by the FHIR group into PHP classes, complete with markup and type hinting.

There are 2 important things to note with this section:

  1. Your exact implementation will probably vary, don't hesitate to ask if you need some help
  2. The class generation should be run ONCE per FHIR version. Once the classes have been generated they should only ever be re-generated if your server switches to a new FHIR spec

Generation Example

require __DIR__.'/vendor/autoload.php';

$schemaPath = 'schema/path';

// first, build new configuration class
$config = new \DCarbone\PHPFHIR\Config([
    // The path to look look for and optionally download source XSD files to
    'schemaPath'  => __DIR__ . '/../input',

    // The path to place generated type class files
    'classesPath' => __DIR__ . '/../output',

    // If true, will use a noop null logger
    'silent'      => false,

    // If true, will skip generation of test classes
    'skipTests'   => false,

    // Map of versions and configurations to generate
    // Each entry in this map will grab the latest revision of that particular version.  If you wish to use a specific
    // version, please see https://www.hl7.org/fhir/directory.html
    'versions'    => [
        'DSTU1' => [
            // Source URL
            'url'       => 'https://hl7.org/fhir/DSTU1/fhir-all-xsd.zip',
            // Namespace to prefix the generated classes with
            'namespace' => '\\HL7\\FHIR\\DSTU1',
        ],
        'DSTU2' => [
            'url'          => 'https://hl7.org/fhir/DSTU2/fhir-all-xsd.zip',
            'namespace'    => '\\HL7\\FHIR\\DSTU2',
            'testEndpoint' => 'https://hapi.fhir.org/baseDstu2',
        ],
        'STU3'  => [
            'url'          => 'https://hl7.org/fhir/STU3/fhir-all-xsd.zip',
            'namespace'    => '\\HL7\\FHIR\\STU3',
            'testEndpoint' => 'https://hapi.fhir.org/baseDstu3',
        ],
        'R4'    => [
            'url'          => 'https://www.hl7.org/fhir/R4/fhir-all-xsd.zip',
            'namespace'    => '\\HL7\\FHIR\\R4',
            'testEndpoint' => 'https://hapi.fhir.org/baseR4',
        ],
        'R5' => [
            'url'          => 'https://hl7.org/fhir/R5/fhir-all-xsd.zip',
            'namespace'    => '\\HL7\\FHIR\\R5',
            'testEndpoint' => 'https://hapi.fhir.org/baseR5',
        ]
    ],
]);

// next, build definition class
$version_config = new \DCarbone\PHPFHIR\Config\VersionConfig($config, $config->getVersion('R5'));
$definition = new \DCarbone\PHPFHIR\Definition($version_config);
$definition->buildDefinition();

$builder = new \DCarbone\PHPFHIR\Builder($config, $definition);
$builder->render();

Using the above code will generate class files under the included output directory, under the namespace HL7\\FHIR\\{version}

If you wish the files to be placed under a different directory, pass the path in as the 2nd argument in the generator constructor.

If you wish the classes to have a different base namespace, pass the desired NS name in as the 3rd argument in the generator constructor.

Data Querying

There are a plethora of good HTTP clients you can use to get data out of a FHIR server, so I leave that up to you.

Response Parsing

As part of the class generation above, a response parsing class called PHPFHIRResponseParser will be created and added into the root namespace directory. It currently supports JSON and XML response types.

The parser class takes a single optional boolean argument that will determine if it should attempt to load up the generated Autoloader class. By default it will do so, but you are free to configure your own autoloader and not use the generated one if you wish.

Parsing Example

require 'path to PHPFHIRResponseParserConfig.php';
require 'path to PHPFHIRResponseParser.php';

// build config
$config = new \YourConfiguredNamespace\PHPFHIRResponseParserConfig([
    'registerAutoloader' => true, // use if you are not using Composer
    'libxmlOpts' => LIBXML_COMPACT | LIBXML_NSCLEAN // choose different libxml arguments if you want, ymmv.
]);

// build parser
$parser = new \YourConfiguredNamespace\PHPFHIRResponseParser($config);

// provide input, receive output.
$object = $parser->parse($yourResponseData);

Serialization

JSON Serialization

$json = json_encode($object);

XML Serialization

// To get an instance of \DOMElement...
$element = $object->xmlSerialize();

// to get as XML string...
$xml = $element->ownerDocument->saveXML($element);

XML Serialization utilizes DOM.

Testing

As part of class generation, a directory & namespace called PHPFHIRTests is created under the root namespace and output directory.

TODO

  • Implement event or pull-based XML parsing for large responses

Suggestions and help

If you have some suggestions for how this lib could be made more useful, more applicable, easier to use, etc, please let me know.

php-fhir's People

Contributors

brianv avatar dataground avatar dcarbone avatar jxckaroo avatar leonrenkema avatar litlfred avatar mmcev106 avatar mrdm-nl avatar wbroek avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

php-fhir's Issues

Thank you!

Very cool package and thankful it existed. Perfect generation of R4 and saved a lot of time. Thanks!

Extra "value" child elements in 1.0.1

The status of a FHIRComposition was previously JSON encoded as follows:

"status": "preliminary"

In 1.0.1 this changed to the following, which does not follow the R4 spec:

"status": {
    "value": "preliminary"
}

Another example is system under FHIRContactPoint.

I'm hoping to make time to work on a fix for this myself, but that could take a while so I wanted to go ahead and report it.

URL appears as element instead of attribute

I found a problem when using an extension. When I set the URL with setUrl() it is rendered as an XML element instead of an attribute on the extension element.

$assemblyOrder = new FHIRExtension();
$assemblyOrder->setUrl("http://hl7.org/fhir/StructureDefinition/humanname-assembly-order");
$valueCode = new FHIRCode();
$valueCode->setValue($this->getHumanNameAssemblyOrder($patientModel));
$assemblyOrder->setValueCode($valueCode);
$name->addExtension($assemblyOrder);

This gives the following XML:

<extension>
  <valueCode value="NL3"/>
  <url value="http://hl7.org/fhir/StructureDefinition/humanname-assembly-order"/>
</extension>

But should be this instead:

<extension url="http://hl7.org/fhir/StructureDefinition/humanname-assembly-order">
  <valueCode value="NL3"/>
</extension>

Parsing a Bundle resource

I'm trying to parse and loop through this resource: MedicationRequest and I'm missing some method to determine the sort of resource that is included in the FHIRResourceContainer.
Especially for included resources this is difficult because they can be of any type.

foreach ($object->entry as $entry) {
    if ($entry->getSearch()->getMode() == 'include') {
        $entry->getResource()->getPatient(); // type of included resource not known
    }
}

Maybe a method $resource = FHIRResourceContainer->getResource() should be added that returns the resource that is included and then $resource instanceof FHIRPatient can be used to determine the type. Or something like $resource->getResourceName().

'UnexpectedValueException' with message 'Value 'Quantity' is not part of the enum

After installing package and try your example I got :

require __DIR__.'/vendor/autoload.php';
$xsdPath = 'xsd/';
$generator = new \DCarbone\PHPFHIR\ClassGenerator\Generator($xsdPath);
$generator->generate();

Fatal error: Uncaught exception 'UnexpectedValueException' with message 'Value 'Quantity' is not part of the enum DCarbone\PHPFHIR\ClassGenerator\Enum\BaseObjectTypeEnum'

Extra attribute in element

We are using version 2.0.5 of the generated library and when we are generating a dosage the doseQuantity contains an extra value attribute. I'm not sure if I have reported this earlier, I could not find an previous issue.

<?xml version="1.0"?>
<Dosage xmlns="http://hl7.org/fhir">
  <doseQuantity value="1">
    <code value="245"/>
    <system value="urn:oid:2.16.840.1.113883.2.4.4.1.900.2"/>
    <unit value="STUK"/>
    <value value="1"/>
  </doseQuantity>
  <route>
    <coding>
      <code value="9"/>
      <display value="Oraal"/>
      <system value="urn:oid:2.16.840.1.113883.2.4.4.9"/>
    </coding>
  </route>
  <sequence value="1"/>
  <text value="1x daags 1 stuks"/>
  <timing>
    <repeat>
      <frequency value="1"/>
      <period value="1"/>
      <periodUnit value="d"/>
      <timeOfDay value="08:00:00"/>
    </repeat>
  </timing>
</Dosage>

When validating it produces this error:

Error @ /f:Dosage/f:doseQuantity (line 3, col27) : Undefined attribute '@value' on doseQuantity for type Quantity (properties = [Quantity.id, Quantity.extension, Quantity.value, Quantity.comparator, Quantity.unit, Quantity.system, Quantity.code])

ResourceContainers may only contain 1 object, "0" values provided

I'm getting this error when trying to parse a resource with one contained resource. I believe there is a bug in how the ResourceContainer is constructed. The constructor expects one element in the parameter, but the parser constructs it with no parameters and then calls the setter separately.

Version used: the master branch of today, 2018-05-29. FHIR STU3.

For the sake of discussion, the constructor of FHIRResourceContainer:

    public function __construct($data = [])
    {
        if (is_object($data)) {
            $this->{sprintf('set%s', substr(strrchr(get_class($data), 'FHIR'), 4))}($data);
        } else if (is_array($data)) {
            if (1 === ($cnt = count($data))) { // <-- always expects something in the parameter!
                $this->{sprintf('set%s', key($data))}($data);
            } else {
                throw new \InvalidArgumentException(sprintf('ResourceContainers may only contain 1 object, "%d" values provided', $cnt));
            }
        } else if (null !== $data) {
            throw new \InvalidArgumentException('$data expected to be object or array, saw '.gettype($data));
        }
    }

The caller is (in the case of JSON) PHPFHIRResponseParser::_parseJsonObject():

    private function _parseJsonObject($jsonEntry, $fhirElementName)
    {
        if ('html' === $fhirElementName) {
            return $jsonEntry;
        }

        if (false !== strpos($fhirElementName, '-primitive') || false !== strpos($fhirElementName, '-list')) {
            return $jsonEntry;
        }

        $map = $this->_tryGetMapEntry($fhirElementName);

        $fullClassName = $map['fullClassName'];
        $properties = $map['properties'];

        $object = new $fullClassName; // <-- passes no parameters!

        // ...

I fixed it in my case by only throwing the InvalidArgumentException if the count is greater than one, allowing the use case of zero arguments + calling a setter. But is this the correct way to fix this? If so, I can create a PR.

Another possible fix is to default the constructor parameter to null instead of an empty array.

User Notice: Could not find mapped property called "_value" on object "Identifier".

First, thank you very much for this excellent project. This has saved people thousands of hours of development time!

I was trying to work with the Cerner API (Sandbox) at https://fhir-open.sandboxcerner.com/dstu2/0b8a0111-e8e6-4c26-a91c-5069cbc6b1ca - it's an open sandbox. It used the DSTU2 standard. When trying to retrieve Person and Patient data I was seeing a notice that the "_value" property could not be mapped.

ย PHPFHIRResponseParser->_parseJsonObject(array('use' => 'usual', 'type' =>ย array('coding' =>ย array(array('system' => 'http://hl7.org/fhir/v2/0203', 'code' => 'AN', 'display' => 'Account number', 'userSelected' =>ย false)), 'text' => 'Federated Person Principal'), 'system' => 'urn:oid:2.16.840.1.113883.3.13.6', 'value' => 'URN:CERNER:IDENTITY-FEDERATION:REALM:0B8A0111-E8E6-4C26-A91C-5069CBC6B1CA:PRINCIPAL:ABC123', '_value' =>ย array('extension' =>array(array('url' => 'http://hl7.org/fhir/StructureDefinition/rendered-value', 'valueString' => 'URN:CERNER:IDENTITY-FEDERATION:REALM:0B8A0111-E8E6-4C26-A91C-5069CBC6B1CA:PRINCIPAL:ABC123'))), 'period' =>ย array('start' => '2017-09-26T05:00:00.000Z', 'end' => '2019-01-02T05:00:00.000Z')), 'Identifier')inย PHPFHIRResponseParser.phpย line 197
--

I know it's just a notice, so it shouldn't be effecting production. In case anyone else see's this error, you could skip the parameter using the switch statement. Just a quick fix. I'm sure there's a better way of handling this issue.

switch($k) { case 'resourceType': case '_value': continue 2; case 'fhir_comments': continue 2; }

Underscore properties (e.g. _xmlns) should be private

Hey @dcarbone ,

It's me again :) I have been extensively working with your FHIR libs - so before I start: THANK YOU greatly for creating them. Keep up the awesome work! โค๏ธ

As you might remember from my earlier issues created, I have been implementing your libraries in Doctrine environment by extending them on my MongoDb-ODM document-classes. In past, we turned public properties into protected, which works VERY WELL.

But I have one more request/suggestion: can we turn underscore properties (e.g. _xmlns and such) to private ones, so that they don't create noise in Doctrine ODM/ORM documents/entities? You actually already created few private properties there (like those for ongoing validation work you plan to implement in future). Because when they are accessible by ORM/ODM assets, resources (e.g. API Resources) using them mis-identify them as actual collection fields or table columns. These private properties can still be used in original FHIR classes of yours and in future, if need be, we can add public getters/setters for them.

What you think? Doable?

Question to users: How often do you use multiple versions in the same codebase?

As part of my refactor branch, I am working on improving the usability and efficiency of the generated code. A piece of this is that I am now defining a suite of constants (viewable here: constants.php). Due to limitations with older versions of PHP that I would still like to support, however, these are currently defined in the global namespace.

This would, of course, conflict if you expected to be able to generate code for multiple versions of FHIR. This could be solved by wrapping constants in a container class, but I would like to avoid that if possible.

So the question i pose is: how often do you use multiple versions in the same code base?

It would not be the end of the world to wrap this output in a namespaced Constants class or something, or even break it up into groups like GenerationMetadata, FHIRTypes, FHIRClasses, etc., and reference those instead.

I may go ahead and do this anyway, but I am curious how often this case is used in the wild.

Double quotes when json_encode is used

Thanks for the great library!

I'm attempting to create a simple Observation resource using FHIR 3.0.1. I generated all of the PHP classes from a downloaded set of XSD files with no issue using the instructions here. I'm running into a strange issue when I attempt to json_encode my object. See some sample code below:

$observation = new FHIRObservation();
$id = new FhirId();
$id->setValue("1234");
$observation->setId($id);
$issued = new FHIRInstant();
$issued->setValue(Carbon::now()->toIso8601String());
$observation->setIssued($issued);
var_dump(json_encode($observation));
die();

This produces:

'{"id":"\"1234\"","resourceType":"Observation","issued":"\"2018-02-09T19:44:53+00:00\""}'

As you can see, it looks like the id and issued properties are being escaped, but the resourceType property is fine. Perhaps I'm missing something obvious - can anyone lend a hand?

JSON serialization is implemented incorrectly

Hi,

Great library, thank you for open sourcing it!

I found a bug when serializing FHIR objects to JSON. Serializing the Patient.json example from the FHIR website will produce the output below, where quotes and whitespace a escaped multiple times.

The reason is because several of the jsonSerialize() methods are returning serialized JSON via json_encode(). The method jsonSerialize() should actually just return basic PHP types (string, integer, float, array, or object) which are then serialized recursively at the top-level json_encode() call.

It's an easy fix, would you like me to fix it and issue a pull request? We will need to regenerate dcarbone/php-fhir-generated as well after this repo is patched.

Example:
{"id":"\"example\"","resourceType":"Patient","text":"{\"status\":\"\\\"generated\\\"\",\"div\":\"<div xmlns=\\\"http:\\\/\\\/www.w3.org\\\/1999\\\/xhtml\\\">\\n\\t\\t\\t<table>\\n\\t\\t\\t\\t<tbody>\\n\\t\\t\\t\\t\\t<tr>\\n\\t\\t\\t\\t\\t\\t<td>Name<\\\/td>\\n\\t\\t\\t\\t\\t\\t<td>Peter James \\n <b>Chalmers<\\\/b> (&quot;Jim&quot;)\\n <\\\/td>\\n\\t\\t\\t\\t\\t<\\\/tr>\\n\\t\\t\\t\\t\\t<tr>\\n\\t\\t\\t\\t\\t\\t<td>Address<\\\/td>\\n\\t\\t\\t\\t\\t\\t<td>534 Erewhon, Pleasantville, Vic, 3999<\\\/td>\\n\\t\\t\\t\\t\\t<\\\/tr>\\n\\t\\t\\t\\t\\t<tr>\\n\\t\\t\\t\\t\\t\\t<td>Contacts<\\\/td>\\n\\t\\t\\t\\t\\t\\t<td>Home: unknown. Work: (03) 5555 6473<\\\/td>\\n\\t\\t\\t\\t\\t<\\\/tr>\\n\\t\\t\\t\\t\\t<tr>\\n\\t\\t\\t\\t\\t\\t<td>Id<\\\/td>\\n\\t\\t\\t\\t\\t\\t<td>MRN: 12345 (Acme Healthcare)<\\\/td>\\n\\t\\t\\t\\t\\t<\\\/tr>\\n\\t\\t\\t\\t<\\\/tbody>\\n\\t\\t\\t<\\\/table>\\n\\t\\t<\\\/div>\"}","identifier":["{\"use\":\"\\\"usual\\\"\",\"type\":\"{\\\"coding\\\":[\\\"{\\\\\\\"system\\\\\\\":\\\\\\\"\\\\\\\\\\\\\\\"http:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/hl7.org\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/fhir\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/v2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/0203\\\\\\\\\\\\\\\"\\\\\\\",\\\\\\\"code\\\\\\\":\\\\\\\"\\\\\\\\\\\\\\\"MR\\\\\\\\\\\\\\\"\\\\\\\"}\\\"]}\",\"system\":\"\\\"urn:oid:1.2.36.146.595.217.0.1\\\"\",\"value\":\"\\\"12345\\\"\",\"period\":\"{\\\"start\\\":\\\"\\\\\\\"2001-05-06\\\\\\\"\\\"}\",\"assigner\":\"{\\\"display\\\":\\\"\\\\\\\"Acme Healthcare\\\\\\\"\\\"}\"}"],"active":"true","name":["{\"use\":\"\\\"official\\\"\",\"family\":\"\\\"Chalmers\\\"\",\"given\":[\"\\\"Peter\\\"\",\"\\\"James\\\"\"]}","{\"use\":\"\\\"usual\\\"\",\"given\":[\"\\\"Jim\\\"\"]}","{\"use\":\"\\\"maiden\\\"\",\"family\":\"\\\"Windsor\\\"\",\"given\":[\"\\\"Peter\\\"\",\"\\\"James\\\"\"],\"period\":\"{\\\"end\\\":\\\"\\\\\\\"2002\\\\\\\"\\\"}\"}"],"telecom":["{\"use\":\"\\\"home\\\"\"}","{\"system\":\"\\\"phone\\\"\",\"value\":\"\\\"(03) 5555 6473\\\"\",\"use\":\"\\\"work\\\"\",\"rank\":\"1\"}","{\"system\":\"\\\"phone\\\"\",\"value\":\"\\\"(03) 3410 5613\\\"\",\"use\":\"\\\"mobile\\\"\",\"rank\":\"2\"}","{\"system\":\"\\\"phone\\\"\",\"value\":\"\\\"(03) 5555 8834\\\"\",\"use\":\"\\\"old\\\"\",\"period\":\"{\\\"end\\\":\\\"\\\\\\\"2014\\\\\\\"\\\"}\"}"],"gender":"\"male\"","birthDate":"\"1974-12-25\"","deceasedBoolean":"false","address":["{\"use\":\"\\\"home\\\"\",\"type\":\"\\\"both\\\"\",\"text\":\"\\\"534 Erewhon St PeasantVille, Rainbow, Vic 3999\\\"\",\"line\":[\"\\\"534 Erewhon St\\\"\"],\"city\":\"\\\"PleasantVille\\\"\",\"district\":\"\\\"Rainbow\\\"\",\"state\":\"\\\"Vic\\\"\",\"postalCode\":\"\\\"3999\\\"\",\"period\":\"{\\\"start\\\":\\\"\\\\\\\"1974-12-25\\\\\\\"\\\"}\"}"],"contact":["{\"relationship\":[\"{\\\"coding\\\":[\\\"{\\\\\\\"system\\\\\\\":\\\\\\\"\\\\\\\\\\\\\\\"http:\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/hl7.org\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/fhir\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/v2\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\/0131\\\\\\\\\\\\\\\"\\\\\\\",\\\\\\\"code\\\\\\\":\\\\\\\"\\\\\\\\\\\\\\\"N\\\\\\\\\\\\\\\"\\\\\\\"}\\\"]}\"],\"name\":\"{\\\"family\\\":\\\"\\\\\\\"du March\\\\\\\\u00e9\\\\\\\"\\\",\\\"given\\\":[\\\"\\\\\\\"B\\\\\\\\u00e9n\\\\\\\\u00e9dicte\\\\\\\"\\\"]}\",\"telecom\":[\"{\\\"system\\\":\\\"\\\\\\\"phone\\\\\\\"\\\",\\\"value\\\":\\\"\\\\\\\"+33 (237) 998327\\\\\\\"\\\"}\"],\"address\":\"{\\\"use\\\":\\\"\\\\\\\"home\\\\\\\"\\\",\\\"type\\\":\\\"\\\\\\\"both\\\\\\\"\\\",\\\"line\\\":[\\\"\\\\\\\"534 Erewhon St\\\\\\\"\\\"],\\\"city\\\":\\\"\\\\\\\"PleasantVille\\\\\\\"\\\",\\\"district\\\":\\\"\\\\\\\"Rainbow\\\\\\\"\\\",\\\"state\\\":\\\"\\\\\\\"Vic\\\\\\\"\\\",\\\"postalCode\\\":\\\"\\\\\\\"3999\\\\\\\"\\\",\\\"period\\\":\\\"{\\\\\\\"start\\\\\\\":\\\\\\\"\\\\\\\\\\\\\\\"1974-12-25\\\\\\\\\\\\\\\"\\\\\\\"}\\\"}\",\"gender\":\"\\\"female\\\"\",\"period\":\"{\\\"start\\\":\\\"\\\\\\\"2012\\\\\\\"\\\"}\"}"],"managingOrganization":"{\"reference\":\"\\\"Organization\\\\\\\/1\\\"\"}"}

Config Constructor fails when XsdPath not provided

Creating a Config object without passing an array with the XsdPath defined fails because the call to setXsdPath() in the constructor won't find the directory null that it's passed when $this->xsdPath isn't set.

Workaround: Pass in the XsdPath in an initialisation array rather than using setXsdPath() after construction

Database model

Hi, is there a way to generate database model from those FHIR Resources objects? Is there another project that we could see with this being done? Thanks

is FHIR free to get data?

hello,

is FHiR free to get data from HL7?
how to use 'php-fhir' with my server? how can I prepare the server?

Thank you

SimpleQuantity serialising twice

I've been using the Generator very successfully against DSTU-2 (from https://www.hl7.org/fhir/fhir-all-xsd.zip on 22-Feb-2016). I've grabbed the sample Immunisation xml from https://www.hl7.org/fhir/immunization-example.xml.html. It parses in beautifully. However, taking that parsed object (which only contains one SimpleQuantity under doseQuantity) and using xmlSerialise() to do a unit test produces:

	<doseQuantity>
		<value value="5" />
		<system value="http://unitsofmeasure.org" />
		<code value="mg" />
		<value value="5" />
		<system value="http://unitsofmeasure.org" />
		<code value="mg" />
	</doseQuantity>

where the SimpleQuantity is serialised out twice. I think I've tracked this down to the parent::xmlSerialize(true, $sxe); in FHIR\DSTU2\SimpleQuantity.php (which is in my root directory for this) - remove that line and you just get one set of quantities.

It seems odd that the classes Age, Count, Distance, Duration, etc together with SimpleQuantity should be in the root rather than under FHIRElement in the generated PSR4 tree? The .xsd has SimpleQuantity with base="Quantity" if that helps

Currently, I've just commented out the parent::xmlSerialize in my source, but thought I should flag this as an potential issue.

Permission denied

I installed php-fhir in a directory with the same name, using composer on a linux server. Then created a php file to create the classes, just like the example. The problem is that I can't even upload the file with ftp as the permission is denied; then I upload it using CPanel, but when running it I get errors related to permissions too.

Purpose of FHIRResourceContainer?

Why are resources wrapped in FHIRResourceContainer? It looks like it's an alternative approach for polymorphism. I also can't tell what's in a FHIRResourceContainer since it doesn't track which field is holding the resource. I had to write a helper to extract resources by class. My gut's telling me I'm using this wrong but I'm not sure where to start. Thank you for looking at this question!

fhir_comments not supported on Meta element

Here is message form exception: "Could not find mapped property called "fhir_comments" on object "Meta". This could indicate malformed response or bug in class generator."

Error generating classes from xsd

Hello,

I'm trying to use your library in my project, but unfortunately an exception is thrown while executing the generate method.

This is the stack trace I'm getting: stacktrace

This is the code that calls the generate() method:

$xsdDirectory = $this->getXsdDirectory();
$modelDirectory = $this->getModelDirectory();
$generator = new Generator($xsdDirectory, $modelDirectory, 'models');
$generator->generate();

The XSD files I'm using are from FHIR DSTU1 version (0.0.82)
Downloaded from: http://hl7.org/fhir/directory.html

I hope you can help me find out why I'm getting this exception and how to resolve it.
Thanks in advance!

XML attribute override applies to all models with a property of the same name.

Currently the override for xml serialization will apply to any model that has the property defined in the override. It's a little presumptuous to assume this is desired for every model that may have a property with the same name. It would be better if we were specific in which model and which property to override to avoid unintended side effects.

Issue running

Hello!

I am having a few issues trying to get this running & I think it might be because one of your dependencies requires PHP8?

// next, build definition class
$definition = new \DCarbone\PHPFHIR\Definition($config);

Parameter #1 expects type VersionConfig.

Am I missing something? :)

Backport decimal precision handling to v2.x release series

Hello!

Was wondering if there are any plans for a post 2.0.5 release?

Are there issues with the commits post-2.0.5 preventing a new release?

I was looking to use this (well, actually the php-fhir-generated version), but encountered an issue where Significant Digits are lost for Decimal numbers.

Looks like this was address, though, by this commit last June: 2a0461d#diff-704bb99ea7436cef0ee4ec7f90a90e15a514727292315c8814d4b2992d2ed5fcR35

Regards!

Resource properties should be private?

Hey @dcarbone ,

I have a question regarding a so called resource classes, e.g. FHIRDomainResource which introduce their own set of properties. Patient and similar classes extend from that class, but of course the properties coming from parent FHIRDomainResource have nothing to do with Patient (at least as far as I can see in FHIR docs). Properties like $contained, or $extension. Having those properties as non-private pollutes Doctrine ORM/ODM assets and introduces them as if they are part of sub-classes (Patient etc), which they aren't.

So, question is: Does it make sense to have these resource class properties as private? What are your thoughts on this topic? Currently my primary interest is FHIRDomainResource class. There may exist other similar classes in your package I may be unaware of.

And considering those set of properties have their setter/getter pairs anyway, my belief is: having them as private shouldn't hurt anything. Actually having these setters/getters also hurt a lot. So another question is: actually, what is the purpose of these properties, or even those classes in first place? Would it make sense to create totally unrelated package solely dedicated to creating Doctrine ODM/ORM resources?

Thanks.

R4 - TYPE_NAME_RAW constant missing.

I generated from the latest master a new copy of R4 and ran the test suite, skipping Integration tests.

............................................................. 6161 / 6341 ( 97%)
........E

Time: 00:05.514, Memory: 385.00 MB

There was 1 error:

1) HL7\FHIR\R4\PHPFHIRTests\Unit\FHIRRawTest::testCanConstructTypeNoArgs
Error: Undefined constant HL7\FHIR\R4\PHPFHIRConstants::TYPE_NAME_RAW

/Volumes/Nexus/Github/php-fhir/output/HL7/FHIR/R4/FHIRRaw.php:77

ERRORS!
Tests: 6170, Assertions: 27730, Errors: 1.

Screenshot 2023-01-12 at 11 44 30 AM

It does appear that constant is now missing. Unsure at the moment if this was parser changes or some change to R4.

FHIRBoolean::getValue() return type

I think this might be under the TODO section as "Typecast scalar values in XML responses to proper PHP type". If that is the same concept, then I just need some direction to make a PR. I can't find what in this code base is generating that method in the generated class.

I'm using the generated STU3 with much success but my IDE noted that the FHIRBoolean.php file is claiming in the docblock to return a string for getValue and it actually returns a boolean. I would expect a boolean so how do I fix this? I'm parsing a JSON file and maybe that makes a difference versus XML?

https://github.com/dcarbone/php-fhir-generated/blob/STU3/src/PHPFHIRGenerated/FHIRElement/FHIRBoolean.php#L82

_fieldValidation property as protected

@dcarbone , hello!

If possible, let's have _fieldValidation field of code-primitive-list types with protected access please - currently, they are private. Sample classes are almost all of them ending with List in their classnames (e.g. FHIRNameUseList). Last time we discussed the topic of validation, you said it might take some time until you finalize it. So I am attempting to create my basic validation processes for now (mostly trait based) and for that reason, need an access to the aforementioned property (_fieldValidation). Thanks!

Idea to make the PHP code less verbose

Not a bug but maybe a nice improvement.

I'm testing the generated code and writing some FHIR resources and the PHP code looks like this. There are a lot of elements that have one value or a fixed number of values.

$p = new FHIRPatient();
$bool = new FHIRBoolean();
$bool->setValue('true');
$p->setActive($bool);

$gender = new \PHPFHIRGenerated\FHIRElement\FHIRAdministrativeGender();
$gender->setValue('male');
$p->setGender($gender);

Maybe it is an idea to introduce a __construct so the default values can be set while constructing the objects? With those the code could look like this, a lot shorter and no need for temporary variables.

$p = new FHIRPatient();
$p->setActive(new FHIRBoolean('true'));
$p->setGender(new FHIRAdministrativeGender('male'));

And maybe thinking ahead some FHIR concepts could be translated implicit from PHP native types to their FHIR equivalent. For example a boolean has only two valid values in FHIR, so the following code can be shortened:

$bool = new FHIRBoolean();
$bool->setValue('true');
$p->setActive($bool);

to this with the same meaning:

$p->setActive(true);

Running generate.php and getting Logger related compatibility errors

Hi There

I am following the steps in the read me and encountering:

php ./bin/generate.php
PHP Fatal error: Declaration of MyENA\DefaultLogger::log($level, $message, array $context = []) must be compatible with Psr\Log\AbstractLogger::log($level, Stringable|string $message, array $context = []): void in C:\xampp\htdocs\php-fhir\vendor\dcarbone\php-fhir\vendor\myena\default-logger\src\DefaultLogger.php on line 122

I have tried adding MyENA and PSR as require commans or adding them to composer.json but having no luck

Any pointer would be greatly appreciated might be that i've installed in the wrong place I can admit i don't have a lot of experience with composer.

Kind Regards

Martin

Parsing extensions in json

I found that there is a trick used in the JSON format to support extensions on a simple value. But the library appears not to support it. When I switch to the XML format there is no problem.

I get the following error when parsing an Organization ErrorException : Could not find mapped property called "_name" on object "Organization".

"name": "Apotheek Janssen B.V.",
"_name": {"extension": [
{
      "url": "http://hl7.org/fhir/StructureDefinition/TBD",
       "valueString": "Legal"
},
{
      "url": "http://hl7.org/fhir/StructureDefinition/TBD",
      "valueBoolean": true
}
]},
<name value="Apotheek Janssen B.V.">
         <extension url="http://hl7.org/fhir/StructureDefinition/TBD">
              <valueString value="Legal">
              </valueString>
         </extension>
         <extension url="http://hl7.org/fhir/StructureDefinition/TBD">
              <valueBoolean value="true">
              </valueBoolean>
        </extension>
</name>

For now there is no problem because we can switch to the XML format but maybe some nice feature to support.

[Note] Fields with default value of NULL

Hey @dcarbone ! First I wanted to thank for your quick support regarding #49 and #50 !

With this ticket I want to note that in PHP, you don't need to initiate class properties with NULL value, as it is already done by default when you declare those properties. So something like this is unnecessary:

public $fieldName = null;

Declaring already initializes them to a null value:

public $fieldName;

Thanks!

Custom profiles

Hi, I am looking for a PHP FHIR client model code generation library that supports profiles other than core STU3/R4. This library looks great - and about the only one for PHP - but unfortunately generates code based on the xsd's instead of xml/json structure definitions, like the libraries for other languages do.
I was wondering why it was chosen to do so, and whether or not is is possible or planned to support structure definitions instead? Or do you know of other ways to e.g. generate xsd's based on custom profiles? In particular I'd like to implement model classes supporting the dutch HL7/MedMij standards.
Thanks!

Escape @ signs in DocBlocks

Hi again,

Having words starting with @ sign (e.g. @value , @id) in DocBlock is causing trouble with Symfony's annotation libraries. Symfony attempts to resolve them as valid annotation bits, requesting to provide classes for such resolution:

image

If escaped (e.g. \@value) this problem is fixed. I realize this might cause DocBlocks to look uglier. But nevertheless, I have to ask: Would it be possible to escape all @ signs in comments please? Thanks.

P.S.: This problem was actually raised here 2 years ago - doctrine/annotations#169 but Doctrine team decided to bin it. And because of that, it's impossible to extend generated FHIR classes to be used as Doctrine entities.

HTML output for a narrative element

I am trying to generate a narrative for a patient but the generated xml doesnt look correct.

Below is the generated XML where the actual text is added to a value attribute of the div element and the XML namespace is missing.

<text> <status value="generated"/> <div value="&lt;p&gt;Voorbeeld van een 'Patient' zoals verder samengesteld tijdens de HL7 WGM NL 15-04-2016 jl. Deze discussie heeft diverse uitzoekpunten opgeleverd zoals hier gedocumenteerd.&lt;/p&gt;"/> </text>

When I change the following line in FHIRNarrative.php
$divElement = $sxe->addChild('div', (string)$this->div); $divElement->addAttribute('value', (string)$this->div);

to

$divElement = $sxe->addChild('div', (string)$this->div, "http://www.w3.org/1999/xhtml"); //$divElement->addAttribute('value', (string)$this->div);

The output does looks better besides that the <p> elements are encoded with htmlentities.

<text> <status value="generated"/> <div xmlns="http://www.w3.org/1999/xhtml">&lt;p&gt;Voorbeeld van een 'Patient' zoals verder samengesteld tijdens de HL7 WGM NL 15-04-2016 jl. Deze discussie heeft diverse uitzoekpunten opgeleverd zoals hier gedocumenteerd.&lt;/p&gt; </div> </text>

I following this example as a reference https://simplifier.net/NictizSTU3/nl-core-patient-example-1/~overview
The XSD release is STU3

TypeError : strlen(): Argument #1 ($string) must be of type string, bool given in FHIRTiming

I am getting the following error TypeError : strlen(): Argument #1 ($string) must be of type string, bool given when trying to parse a FHIRTiming object with the following input data:

<timing>
  <repeat>
     <frequency value="1"/>
     <period value="1"/>
     <periodUnit value="d"/>
  </repeat>
</timing>

The error is caused by a check if there are decimals. When there are no decimals strstr will return false and strlen(false) will produce this error.

https://github.com/dcarbone/php-fhir/blob/master/template/properties/methods/primitive/decimal_type.php#L39

Besides that is frequency of type PositiveInt so a decimal should not be accepted.

Get nodes details from FHIR after parsing

Hi there,
Is there a way to reach "Patient" node without convetting the response to json with json_encode in PHP after :
$parser->parse($input) ;
I got PHPFhirResponse interface abd I need to reach the patient node without json encode.

Would it make sense to associate resources by reference?

In my current use case I'm building a FHIRQuestionnaireResponse that involves nesting a bunch of FHIRQuestionnaireResponseItem instances. Since FHIRQuestionnaireResponseItem::addItem() does not accept items by references, I am not able to modify an item after adding it to another item (or the parent response). I think that means I'm going to have to do my data manipulation using nested arrays mimicking the FHIRQuestionnaireResponse structure I want, then do another loop to actually create the FHIR classes after the data is finalized.

There's no expectation at all for you to work on this @dcarbone. I'm mainly just curious what you think of the idea.

Access levels of fields in generated classes

This generator creates "private" fields for classes generated. Would it be possible to switch this to "protected", as it is impossible to extend the generated classes otherwise? Thanks.

R4 Builder throws exception Enum

PHP 8.1
[09-Sep-2022 22:00:22 UTC] PHP Fatal error: Uncaught UnexpectedValueException: Value 'AccountStatusEnum' is not part of the enum DCarbone\PHPFHIR\Enum\PrimitiveTypeEnum in C:\xampp\htdocs\php-fhir\vendor\myclabs\php-enum\src\Enum.php:245
Stack trace:
#0 C:\xampp\htdocs\php-fhir\vendor\myclabs\php-enum\src\Enum.php(73): MyCLabs\Enum\Enum::assertValidValueReturningKey('AccountStatusEn...')
#1 C:\xampp\htdocs\php-fhir\src\Definition\TypeDecorator.php(266): MyCLabs\Enum\Enum->__construct('AccountStatusEn...')
#2 C:\xampp\htdocs\php-fhir\src\Definition.php(80): DCarbone\PHPFHIR\Definition\TypeDecorator::determinePrimitiveTypes(Object(DCarbone\PHPFHIR\Config\VersionConfig), Object(DCarbone\PHPFHIR\Definition\Types))
#3 C:\xampp\htdocs\php-fhir\bin\generate.php(468): DCarbone\PHPFHIR\Definition->buildDefinition()
#4 {main}
thrown in C:\xampp\htdocs\php-fhir\vendor\myclabs\php-enum\src\Enum.php on line 245

FHIRResourceContainer constructor

Hi,

When I generate the FHIR model from the latest code in master, I bump into a problem with the constructor of the FHIRResourceContainer. This is my test code:

use PHPFHIRGenerated\FHIRResourceContainer;
use PHPFHIRGenerated\FHIRDomainResource\FHIRMedicationRequest;

require 'vendor/autoload.php';

$container = new FHIRResourceContainer(new FHIRMedicationRequest());

When I try to run this I get the following error Call to undefined method PHPFHIRGenerated\FHIRResourceContainer::set(). It not clear to me how this is supposed to work, there seems to be a problem in this line of the FHIRResourceContainer, $n = ltrim(strrchr(get_class($data)), "\FHIR"); PHPstorm complains that the required param for strrchr is missing.

When I try it like this $container = new FHIRResourceContainer(new FHIRMedicationRequest()); I get the same error but triggered on another line in the code.

Autoloaded file `files/errors.php` changes application behavior

I'm using this library in an Symfony application, and I noticed that my application doesn't run at all anymore after upgrading to Symfony 5.0. After debugging I found out that the culprit is the files/errors.php file that "just" replaces the PHP error handler that converts everything (notices, warnings, deprecations, etc.) to ErrorException's, which are fatal errors.

This file is automatically loaded by the Composer autoloader in the composer.json:

  "autoload": {
    "files": [
      "files/constants.php",
      "files/funcs.php",
      "files/errors.php" <---
    ],
    "psr-4": {
      "DCarbone\\PHPFHIR\\": "src/"
    }
  },

One does not expect that his application behavior (silently) is changed by just adding a Composer dependency!

The id property is always added as a child element instead of an attribute

In MethodGenerator.php implementXMLSerialize() method,
The id property is always added as a new child element. I think this is incorrect behavious.
Looking at the fhir spec the id of an element is always specified as an attribute of that element.

It could be solved by doing a check on the property value, and in case of an id, add it as attribute.

Generation of class properties from elements in XSD choice definition is not working

<xs:choice minOccurs="1" maxOccurs="1" >
  <xs:annotation>
    <xs:documentation>The time or time-period the observed values are related to. This is usually either the time of the procedure or of specimen collection(s), but very often the source of the date/time is not known, only the date/time itself.</xs:documentation>
  </xs:annotation>
  <xs:element name="diagnosticDateTime" type="dateTime"/>
  <xs:element name="diagnosticPeriod" type="Period"/>
</xs:choice>

The PropertyGenerator does not seem to handle this choice element correctly. The output is a class without the diagnosticDateTime and diagnosticPeriod properties, If I put the elements on the same level as the choice definition they are picked up and created on the model correctly.

Edit: fixed in version 0.4.2

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.