Installation
composer require ardenexal/fhir-path
Ensure your project uses PHP 8.0+ (check composer.json constraints).
Basic Usage
use Ardenexal\FhirPath\FhirPath;
$fhirPath = new FhirPath();
$result = $fhirPath->evaluate('Patient.name', [
'resourceType' => 'Patient',
'name' => [
['family' => 'Doe', 'given' => ['John']]
]
]);
// Returns: [["family" => "Doe", "given" => ["John"]]]
First Use Case Query FHIR resources (e.g., JSON/XML) stored in a database or API response:
$patientData = json_decode(file_get_contents('patient.json'), true);
$activeAllergies = $fhirPath->evaluate('Patient.allergyIntolerance.where(active=true)', $patientData);
Querying Nested FHIR Resources Use dot notation for hierarchical access:
$observations = $fhirPath->evaluate('Observation.valueQuantity.value', $bundle);
Filtering with Predicates
Combine where() and logical operators:
$criticalPatients = $fhirPath->evaluate(
'Patient.where(condition.where(code.coding.where(system="http://loinc.org" and code="38161-5")).exists())',
$data
);
Integration with Eloquent
Store FHIR JSON in a fhir_resources table and query via a model:
class FhirResource extends Model {
protected $casts = ['data' => 'array'];
public function scopeActiveAllergies($query) {
return $query->whereRaw("JSON_CONTAINS(data, '$.resourceType', 'Patient')")
->where(function($q) {
$q->whereJsonContains('data->allergyIntolerance', '$.active', true);
});
}
}
Batch Processing Process FHIR bundles efficiently:
$bundle = json_decode($apiResponse, true);
$entries = collect($bundle['entry'] ?? []);
$results = $entries->map(fn($entry) => $fhirPath->evaluate('Patient.name', $entry['resource']));
Patient.id) in a config or cache layer.Case Sensitivity
FHIR paths are case-sensitive. Use exact matches for resource types (Patient ≠ patient).
Null Handling
Undefined paths return null. Use exists() or default values:
$fhirPath->evaluate('Patient.deceasedDateTime', $data, null);
Complex Predicates
Overly nested where() clauses may hit PHP recursion limits. Break into smaller queries or use collect() for preprocessing.
JSON vs. Array Input The package expects arrays, not JSON strings. Decode responses first:
$data = json_decode($jsonString, true); // Required!
Enable Logging: Wrap evaluations in try-catch to log malformed paths:
try {
$result = $fhirPath->evaluate('Patient.???', $data);
} catch (\Ardenexal\FhirPath\Exception\EvaluationException $e) {
Log::error("FHIR Path Error: " . $e->getMessage());
}
Validate Input: Use json_validate() or a library like spatie/array-to-object to sanitize FHIR data before evaluation.
Custom Functions Extend the evaluator by registering custom functions (if the package supports it):
$fhirPath->registerFunction('customFunc', function($arg) {
return strtoupper($arg);
});
// Usage: `Patient.name.where(given.customFunc())`
Integration with FHIR SDKs
Pair with hl7-fhir/php-fhir for validation before evaluation:
use HL7\FHIR\Parser;
$parser = new Parser();
$resource = $parser->parseResource($jsonString);
$fhirPath->evaluate('Patient.birthDate', $resource->toArray());
Testing Mock FHIR data in tests:
$mockPatient = [
'resourceType' => 'Patient',
'birthDate' => '1980-01-01'
];
$this->assertEquals('1980-01-01', $fhirPath->evaluate('Patient.birthDate', $mockPatient));
How can I help you explore Laravel packages today?