BiPRO Enumerationen mit PHP 8.1 einfach erstellen

Es gibt tatsächlich neue Entwicklungen in Bezug auf die Umsetzung der BiPRO Normen mit PHP. Es wird allerdings sehr technisch werden. Also lehn Dich zurück, nimm Dir ein wenig Zeit und staune. Wir reden über BiPRO Enumerationen mit PHP 8.1.

Seit im Dezember letzten Jahres PHP 8.1 veröffentlicht wurde und somit Enumerationen verfügbar sind, habe ich mal wieder ein wenig ausprobiert, um den Arbeitsaufwand bei der Umsetzung der BiPRO Normen weiter zu minimieren. Es geht Schritt für Schritt in Richtung einer vollständigen Automatisierung.

Automatisierung?

Zunächst geht es um die Erstellung von Entitäten und nun auch endlich Enumerationen, die sowohl die komplexen als auch die simplen BiPRO Typ-Definitionen, sofern sie Enumerationen sind, mit PHP abbilden. Natürlich kann man das auch alles per Hand programmieren. Allerdings kostet das jede Menge Zeit. Da die handwerklichen Schritte an dieser Stelle immer die gleichen sind, bietet sich eine automatische Erstellung von Entitäten und Enumerationen auf Basis der BiPRO Schema Definitionen an. Ein BiPRO Release wird glücklicherweise immer mit allen verwendeten XSD Schema Definitionen ausgeliefert. Ich als Entwickler weiß wegen der dort notierten Definitionen also, wie Entitäten und Enumerationen aussehen müssen. Das kann man also auch automatisiert lösen, so dass mehr Zeit für die Entwicklung von anderen Dingen bleibt. Ein paar Minuten eher am Grill stehen. Oder einfach mal pünktlich zum Fussballspiel erscheinen. Wäre doch mal was …

Die Erstellung von PHP Entitäten und Enumerationen ist wichtig, um im gleichen objektrelationalen Kontext wie das BiPRO Datenschema selbst bleiben zu können. Jeder komplexe Typ aus der BiPRO Definition entspricht einer Entität. Eine Entität ist in diesem Sinne nichts anderes als ein Datenobjekt mit einem eindeutigen Identifier. Dies könnte ein Primärschlüssel aus einer relationalen Datenbank sein, als auch eine UUID aus einem dokumentbasierten Datenhaltungssystem. Entitäten dienen ebenfalls dazu die darin enthaltenen Daten in einem entsprechenden Format ausgeben zu können. Sowohl PHP Soap Webservices können mit einer Struktur aus Entitäten umgehen, um daraus XML zu erstellen, als auch die Transformation von PHP zu JSON ist ein Kinderspiel. Es muss also nicht zwingend ein Soap Webservice am Ende der Entwicklung stehen. Denkbar wäre auch eine Sammlung von REST API Services, die die gleichen Entitäten benutzt, wie ein SOAP Webservice oder die Datenbank. Es dreht sich also alles um die Datenhaltung und Formate.

Wie geht das jetzt mit diesen Enumerationen?

Eigentlich ganz einfach. Enumerationen sind immer eine definierte Menge an Werten, zu denen es im allerbesten Fall auch eine Beschreibung in Form eines Labels gibt. Wenn man so will, reden wir hier von Key / Value Paaren.

Schauen wir uns zunächst mal an, wie die BiPRO Enumerationen definiert.

<xsd:simpleType name="ST_Meldungsart">
      <xsd:restriction base="xsd:string">
         <xsd:enumeration value="Fehler">
            <xsd:annotation>
               <xsd:documentation xml:lang="de">Fehler: Die Verarbeitung ist nicht durchgeführt worden. Es liegt ein fachlicher oder technischer Fehler vor. Weitere Informationen siehe MeldungID</xsd:documentation>
            </xsd:annotation>
         </xsd:enumeration>
         <xsd:enumeration value="Hinweis">
            <xsd:annotation>
               <xsd:documentation xml:lang="de">Hinweis bedeutet kein Fehler, aber weitere Informationen. z.B. Standard OK Meldung.
Weitere Informationen siehe MeldungID</xsd:documentation>
            </xsd:annotation>
         </xsd:enumeration>
         <xsd:enumeration value="Warnung">
            <xsd:annotation>
               <xsd:documentation xml:lang="de">Warnung wiegt schwerer als ein Hinweis und erfordert besondere Aufmerksamkeit.
Weitere Informationen siehe MeldungID</xsd:documentation>
            </xsd:annotation>
         </xsd:enumeration>
      </xsd:restriction>
   </xsd:simpleType>

Ihr seht hier die Definition des simplen Typen ST_Meldungsart, welcher drei Werte beinhaltet. Diese drei Werte haben jeweils eine kleine Beschreibung, die die Werte verständlich erläutern. Diese Informationen können wir nutzen, um daraus eine PHP Enumeration zu erstellen.

<?php
declare(strict_types=1);
namespace Datentypen\Entity;

enum MeldungsartEnum: string
{
    case ST_MELDUNGSART_FEHLER = "Fehler";
    case ST_MELDUNGSART_HINWEIS = "Hinweis";
    case ST_MELDUNGSART_WARNUNG = "Warnung";

    public function getLabel(): string
    {
        return match($this) {
            self::ST_MELDUNGSART_FEHLER => "Fehler: Die Verarbeitung ist nicht durchgeführt worden. Es liegt ein fachlicher oder technischer Fehler vor. Weitere Informationen siehe MeldungID",
            self::ST_MELDUNGSART_HINWEIS => "Hinweis bedeutet kein Fehler, aber weitere Informationen. z.B. Standard OK Meldung. Weitere Informationen siehe MeldungID",
            self::ST_MELDUNGSART_WARNUNG => "Warnung wiegt schwerer als ein Hinweis und erfordert besondere Aufmerksamkeit. Weitere Informationen siehe MeldungID",
        };
    }
}

So sieht dann also unsere Enumeration mit PHP aus. Diese Enumeration beinhaltet alle Informationen, die die Schema-Definition zu diesem simplen Typen auch enthält. Die Enumeration besitzt eine String Restriktion, die einfach nur besagt, dass es sich bei den Werten dieser Enumeration um Strings handelt. Alle drei möglichen Werte wurden als cases notiert. Die zusätzlichen Informationen wurden über die Methode getLabel() implementiert.

Was macht man jetzt damit?

Enumerationen sind hervorragend dafür geeignet, um in Entitäten als Type Hints zu agieren. Aus diesen Type Hints können sich dann zusätzliche Systeme, wie z.B. Doctrine als ORM System, zusätzliche Informationen ziehen.

<?php
declare(strict_types=1);
namespace Nachrichten\Entity;

use Basis\Entity\Objekt;
use Datentypen\Entity\MeldungsartEnum;
use Doctrine\ORM\Mapping as ORM;

#[ORM\Entity()]
#[ORM\Table()]
final class Meldung extends Objekt
{
    ...
    #[ORM\Column(name: 'art_id', nullable: false)]
    protected MeldungsartEnum $artID;

    public function getArtID(): MeldungsartEnum
    {
        return $this->artID;
    }

    public function setArtID(MeldungsartEnum $artID): void
    {
        $this->artID = $artID;
    }
    ...
}

So sieht Typensicherheit aus. Laut BiPRO Definition muss die Eigenschaft artID aus dem komplexen Typen CT_Meldung einem der Werte aus der Enumeration ST_Meldungsart entsprechen. Genau das haben wir jetzt in unserer PHP Entität dargestellt.

Was ist denn jetzt mit dieser Automatisierung?

Als Entwickler kann man das alles natürlich per Hand runter programmieren. Allerdings muss man sich zwangsläufig fragen, ob man sich diesen Aufwand gönnen möchte, und ob man auf derart ermüdende Arbeit tatsächlich Bock hat? Aus eigener Erfahrung sage ich mal, dass das in den meisten Fällen nicht so ist.

Wie wäre es mit einem CLI Befehl, der die PHP Enumeration aus den XSD Definitionen automatisch erstellt und als Datei im entsprechenden Namensraum / Verzeichnis speichert?

c:\MMNewmedia\xampp\htdocs\projekte\bipro\development\vendor\bin>laminas bipro:enumeration -h
Description:
      Converts BiPRO XSD enumerations to PHP 8.1 enumerations.

Usage:
  bipro:enumeration [options] [--] <namespace> <file> <name>

Arguments:
  namespace                                  The namespace of the PHP enumeration to be created. Beware of preceding backslashes!
  file                                       The complete file path to the BiPRO xsd file.
  name                                       The name of the BiPRO datatype

Options:
  -l, --get-label[=GET-LABEL]                Should the getLabel() method be added to the PHP enumeration? [default: false]
  -c, --create-directory[=CREATE-DIRECTORY]  Should the directory path resolved from the namespace be created when it does not exist? [default: false]

Et voilá! Ich habe für mich auf Basis des laminas/laminas-cli Repository ein CLI Command programmiert, welches genau das macht. Auf Basis eines angegebenen Simple Types, der eine Enumeration nach BiPRO Schema darstellt, wird eine PHP Enumeration erstellt und in einem angegebenen Verzeichnis / Namensraum abgelegt. Fortan tippe ich das alles nicht mehr selbst, sondern lasse es mit einem einfachen CLI Kommando erstellen. In einem Bruchteil der Zeit, die ein Wimpernschlag dauert.

c:\MMNewmedia\xampp\htdocs\projekte\bipro\development\vendor\bin>laminas bipro:enumeration Datentypen\Enum c:\MMNewmedia\xampp\htdocs\projekte\bipro\schema\bipro-datentypen-2.6.0.xsd ST_Meldungsart

Fazit

Die BiPRO Definitionen sind mittlerweile so gut definiert, dass eine automatisierte Erstellung, wie ich sie eben gezeigt habe, reibungslos und sehr performant funktionieren kann. Sicherlich hapert es hier und da an ein paar Kleinigkeiten wie Rechtschreibfehler in den Definitionen oder fehlende Dokumentationen innerhalb der XSD Dateien. Aber, so fair muss man einfach sein, damit kann man einfach arbeiten. CLI Kommandos sind dafür wie geschaffen.

Was denkt ihr? Geht es noch einfacher? Wie handhabt ihr Entitäten im BiPRO Kontext? Arbeitet ihr überhaupt mit Entitäten oder bevorzugt ihr eine lose Datenhaltung? Teilt mir Eure Gedanken einfach über die Kommentare mit.

Kommentar verfassen

Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.