HL7 FHIR ด้วยภาษา PHP โดยหมอไผ่

HL7 FHIR ใช้งาน FHIR บน PHP ด้วย PHP-FHIR

ช่วงหลังๆ เรามีการพูดถึงมาตรฐานข้อมูลกันเยอะโดยเฉพาะ HL7 FHIR ที่กำลังมีการศึกษาเพื่อนำมาใช้ในประเทศไทย เพราะจะทำให้การแลกเปลี่ยน เข้าถึงข้อมูลต่างๆ ทำได้ดีขึ้น การใช้ประโยชน์ก็จะทำได้ดีขึ้น

แต่ทีนี้ ขึ้นชื่อว่ามาตรฐานแล้ว สิ่งสำคัญคือต้องมีคนใช้แพร่หลาย เพราะมาตรฐานที่ไม่มีคนใช้ ก็จะไม่เกิดประโยชน์ใดๆ เหมือนใช้รหัส ICD-11 ในประเทศที่ยังใช้ ICD-9

ซึ่งการทำให้แพร่หลายนั้น จะต้องทำให้ง่ายกับการใช้งาน

และการทำให้ง่ายกับการติดตั้งใช้งาน ย่อมจะต้องทำให้มันสามารถใช้บนสิ่งที่เราใช้กันอยู่แล้วได้ สิ่งนั้น คือ Php ที่ เหล่า IT โรงพยาบาลรัฐ แทบจะใช้เป็นกันทั้งประเทศ เพราะจะให้การเริ่มใช้งานทำได้ทันที ไม่ต้องเตรียม หรือ ใช้เวลาในการเรียนรู้/จัดการของภาษาใหม่

ปัญหาคือ ตัวช่วยจัดการ (Library) ต่างๆ ของ HL7 FHIR นั้นส่วนใหญ่จะอยู่บน Java, Python แต่แทบไม่มีการพูดถึง PHP เลย เอกสารก็ไม่มี

หลังจากหามานาน ผมก็เจอเข้ากับตัวหนึ่งคือ PHP FHIR ของ DCarbone และน่าจะเป็นตัวเดียวในขณะนี้ เพราะตัวอื่นที่เจอ เหมือนจะเลิกพัฒนาไปหมดแล้ว

ซึ่งโครงการนี้เอง ก็ดันไม่มี Tutorial หรือ เอกสารสอนการใช้งานซะอีก หลังจากงมอยู่สักพักก็เลยเขียนมาฝากกัน

โดยตัว PHP-FHIR จะเหมือนเป็น script ที่จะสร้าง PHP Class จาก file โครงสร้าง FHIR ครับ แต่ผู้พัฒนานั้นจะมี FHIR class สำเร็จรูปที่สร้างเสร็จแล้วเตรียมไว้ให้

อันนี้เป็น Github ของโครงการหลัก

https://github.com/dcarbone/php-fhir

ส่วนอันนี้จะเป็น class ที่สร้างมาพร้อมใช้จากตัว PHP FHIR ซึ่งเวลาใช้จริงเราจะใช้ตัวนี้ครับ

https://github.com/dcarbone/php-fhir-generated

วันนี้เลยจะมาแสดงการสร้างและใช้ โครงสร้าง HL7 FHIR R4 ผ่าน PHP ซึ่งผมจะใช้ผ่าน Laravel Framework บน Xampp ครับ

เนื่องจากเป็นสิ่งที่ใช้กันเยอะใน รพ รัฐ ผมขออนุมานว่าทุกท่านที่อ่านอยู่ จะต้องพอเขียน PHP ได้เก่งกว่าผมในตอนนี้ เพราะผมพึ่งจะมาเคยเขียน PHP + Laravel กับ post นี้เนี่ยล่ะครับ 55 ดังนั้นขออภัยหากจะดูประหลาดไปบ้าง

สำหรับท่านที่ไม่เคยเขียน Laravel/PHP อาจแวะไปดู Link นี้ก่อนกลับมาทำต่อครับ เป็นภาษาไทย ?

เอาล่ะเริ่มกันเลยครับ ขออนุมานว่า ทุกท่่านมี PHP + Composer และ Laravel อยู่บนเครื่องแล้ว

ให้เริ่มจาก ติดตั้งตัว package ลงใน Project

composer require dcarbone/php-fhir-generated

เสร็จแล้ว ท่านจะเห็น Class จำนวนมากโผล่ขึ้นมาใน DCarbone\PHP-FHIR-Generated ตามรูปครับ ซึ่งจะมีของ FHIR ทุก version ตั้งแต่ 1-4

ผมจะแสดงการสร้างโครงสร้างผู้ป่วย “Patient” พื้นฐาน โดยผมจะใช้วิธี เขียนโครงสร้างบน Controller และส่งไปแสดงผลใน index.blade.php
เริ่มด้วยการสร้าง Controller ขึ้นมาตัวนึง ผมตั้งชื่อว่า FHIRController

php artisan make:controller FHIRController

อย่าลืมขั้นตอนอื่นๆ เช่นการตั้ง route นะครับ ผมไม่ได้พูดถึงตรงนี้ เพราะอนุมานว่าท่านที่อ่านอยู่ทำกันเป็นหมดแล้ว

พอเปิด File Controller ขึ้นมา ให้เราดึง Class FHIRPatient ที่เราพึ่งติดตั้งเข้ามาด้วยคำสั่ง use

หากจะลองกับโครงสร้างตัวอื่น ก็สามารถค้นได้แถวๆนั้นล่ะครับ แต่ให้เน้นหาใน FHIRDomainResource จะเป็นตัวที่ใช้จริงมากกว่าตัวที่เป็นสำหรับงานเบื้องหลัง

use DCarbone\PHPFHIRGenerated\R4\FHIRResource\FHIRDomainResource\FHIRPatient;

แน่นอนว่า ต้องสร้าง ตัวแปรใหม่จาก class FHIRPatient ซึ่งผมจะใส่ข้อมูลพื้นฐานดังรูป

$fhir_p=new FHIRPatient(['gender'=>'female','name'=>[array("given"=>"First","family"=>"Last")],"address"=>[array("city"=>"Bangkok")]]);

การจะดูว่าตัวไหนเป็น array หรือ ใช้ key ไหนในการใส่ข้อมูบ ให้ดูทีตัวเอกสารของ HL7 FHIR หรือ ไล่ดูในตัว FHIRPatient Class ใน PHP ที่เราติดตั้งเข้ามาก็ได้ครับแล้วทดสอบไป ถ้ามันไม่ตรงเดี๋ยวระบบจะฟ้อง error เอง

แค่นี้ล่ะครับ เราก็ได้ชุดข้อมูล FHIRPatient พื้นฐานมาแล้ว ?

เดี๋ยวจะแสดงข้อมูลโดยส่งไปทั้งตัวแปรเลยครับ

return view('fhir.index')->with(['fhir_p'=>$fhir_p]);

ของผมจะใช่ชื่อ file ว่า index.blade.php โดยเก็บไว้ใน folder fhir คำสั่ง return view เลยเป็น fhir.index โดย code ทั้งหมดของ FHIRController จะเป็นแบบนี้ครับ

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use DCarbone\PHPFHIRGenerated\R4\FHIRResource\FHIRDomainResource\FHIRPatient;

class FHIRController extends Controller
{
    //
    public function index()
    {
        $fhir_p=new FHIRPatient(['gender'=>'female','name'=>[array("given"=>"First","family"=>"Last")],"address"=>[array("city"=>"Bangkok")]]);
  
        return view('fhir.index')->with(['fhir_p'=>$fhir_p]);

    }
}

สำหรับการใช้งานก็สามารถ แปลงมันเป็น json ด้วย json_encode แล้วนำไปใช้งาน โดย code ด้านล้างจะเป็น index.blade.php ทีใช้แสดงผล

@extends('layouts.app')
@section('content')

<h1>
This is FHIR
</h1>

{{json_encode($fhir_p)}}

@endsection

ซึ่งเมื่อ run ผ่านคำสั่ง php artisan serve เสร็จก็จะได้แบบนี้ครับ

เพื่อยืนยันว่ารูปแบบถูกต้อง ผมนำ JSON ที่เราสร้างจาก class เมื่อสักครู่ไปตรวจสอบกับ HAPI FHIR testserver ก็พบว่าใช้งานได้และถูกต้องตามรูปแบบมาตรฐาน FHIR

นอกจากการเรียกผ่าน JSON ตรงๆ จะมีวิธีเรียก function จากตัว class ที่ส่งเข้าไป ซึ่งผมไม่แนะนำ
สาเหตุเพราะ ข้อมูลใน $fhir_p ในตอนนี้ ส่วนใหญ่จะไม่ได้เก็บในรูปแบบพื้นฐาน อย่างตัวเลข หรือ ข้อความ แต่จะเก็บเป็น class ข้อมูลเฉพาะ ที่สร้างขึ้นมาเพื่องานนี้

เช่น เพศ (gender) ก็จะเก็บในรูปของ FHIRAdministrativeGender
ถ้าท่านเรียกดูเพศ จาก FHIRPatient ตรงๆ ด้วย getGender() มันจะคืน FHIRAdministrativeGender มาให้ ซึ่งเปิดตรงๆไม่ได้ จะต้องเรียกใช้ Function getValue ซึ่งอยู่ใน FHIRAdministrativeGender อีกรอบนึง

จะต้องเรียกใช้ function getValue() ของ FHIRAdministrativeGender อีกที

ดังนั้น หากเราจะเรียกข้อมูลเพศจาก class FHIRPatient ออกมาเป็นตัวอักษรตรงๆ บน index.blade.php ก็จะเป็น

{{$output->getGender()->getValue()}}

ซึ่งการจะไล่ดู function พวกนี้ ท่านก็จะต้องไปไล่ดู class โดยเริมจาก FHIRPatient และลึกลงไปในแต่ละตัวแปร ว่ามันเก็บไว้ใน class อะไร แล้วไล่ไปดู class นั้นอีกที

เอาล่ะนั่นคือ กรณีที่้เราสร้าง FHIR จากฝั่งเรา และถ้าเราเป็นฝั่งที่รับมาล่ะ?

สุมมุติว่าเรารับเป็นข้อมูล JSON รูปแบบนี้ ซึ่งผมไปดึงมาจาก FHIR Test server

        $json_string='{
            "resourceType": "Patient",
            "id": "1333583",
            "meta": {
              "versionId": "1",
              "lastUpdated": "2020-07-03T20:03:30.586+00:00",
              "source": "#BL9AgjA67KhMR3Uq"
            },
            "text": {
              "status": "generated",
              "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\">JONNY </div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>EXTgroup3</td></tr><tr><td>Address</td><td><span>Ruppertshofen </span></td></tr><tr><td>Date of birth</td><td><span>13 October 1972</span></td></tr></tbody></table></div>"
            },
            "identifier": [ {
              "value": "EXTgroup3"
            } ],
            "name": [ {
              "given": [ "JONNY" ]
            } ],
            "gender": "male",
            "birthDate": "1972-10-13",
            "address": [ {
              "city": "Ruppertshofen"
            } ]
          }';

ท่านจะต้องนำมันเข้าไปยังตัวแปลงที่เรียกว่า Parser ครับ โดย เพิม use ต่อไปนี้ที่ด้านบน

use DCarbone\PHPFHIRGenerated\R4\PHPFHIRResponseParser;

หลังจากนั้นก็สร้าง ตัวแปรจาก class PHPFHIRResponseParser() แล้วโยน JSON ตัวเมื่อกี๊ลงไป จะได้ code สุดท้ายแบบนี้ครับ โดยผมจะเพิ่มเข้าไปจาก code เดิมทั้งสองตัว

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;



use DCarbone\PHPFHIRGenerated\R4\FHIRResource\FHIRDomainResource\FHIRPatient;
use DCarbone\PHPFHIRGenerated\R4\PHPFHIRResponseParser;

class FHIRController extends Controller
{
    //
    public function index()
    {
       
        $json_string='{
            "resourceType": "Patient",
            "id": "1333583",
            "meta": {
              "versionId": "1",
              "lastUpdated": "2020-07-03T20:03:30.586+00:00",
              "source": "#BL9AgjA67KhMR3Uq"
            },
            "text": {
              "status": "generated",
              "div": "<div xmlns=\"http://www.w3.org/1999/xhtml\"><div class=\"hapiHeaderText\">JONNY </div><table class=\"hapiPropertyTable\"><tbody><tr><td>Identifier</td><td>EXTgroup3</td></tr><tr><td>Address</td><td><span>Ruppertshofen </span></td></tr><tr><td>Date of birth</td><td><span>13 October 1972</span></td></tr></tbody></table></div>"
            },
            "identifier": [ {
              "value": "EXTgroup3"
            } ],
            "name": [ {
              "given": [ "JONNY" ]
            } ],
            "gender": "male",
            "birthDate": "1972-10-13",
            "address": [ {
              "city": "Ruppertshofen"
            } ]
          }';



        $parser=new PHPFHIRResponseParser();

        $output=$parser->parse($json_string);
       return view('fhir.index')->with(['output'=>$output]);

    }
}

เมื่อส่ง $output ที่แปลงแล้ว ไปที่ blade.php จะเห็นว่า ผมจะเรียกใช้ function จาก class ได้เหมือนตัวที่เราสร้างเมื่อกี๊แล้ว จะเห็นว่าผมแสดงการดึงชื่อจริง ออกมาจาก class FHIRPatient ให้ดูด้วยครับ ซับซ้อนทีเดียว ?

@extends('layouts.app')
@section('content')

้<h1>

This is FHIR
</h1>

<p>
{{json_encode($output)}}
</p>
{{$output->getName()[0]->getGiven()[0]->getValue()}}
<p>
{{$output->getGender()->getValue()}}


@endsection

ok เสร็จแล้วครับ หวังว่าจะไม่ยาวเกินไป
การใช้รูปแบบนี้ ถึงจะยังซับซ้อนอยู่ แต่น่าจะง่ายกว่าไปเปิดเอกสาร HL7 FHIR แล้วเขียนมือ ซึ่งยากเอาการ แม้แต่กับผู้เชี่ยวชาญเอง หวังว่าเครื่องมือนี้และน่าจะทำให้ทุกท่าน ได้ทดลอง HL7 FHIR กับระบบของ รพ ตัวเองมากขึ้นโดยครับ ?

 

 

Reference :

HL7 FHIR ใช้งาน FHIR บน PHP ด้วย PHP-FHIR

 

แชร์เลย