Vergleich verschiedener PHP-basierter ORM-Frameworks mit Fokus auf ihrem Anwendungspotenzial für Content-Management-Systeme

von Ingmar Szmais 3113419 Databay AG

1. Prüfer: Prof. Dr. rer. nat. Volker Sander 2. Prüfer: Thomas Joussen Reichshof, 26. Dezember 2018

1

Eidesstattliche Erklärung Hiermit versichere ich, dass ich die Seminararbeit mit dem Thema “Vergleich verschiedener PHP-basierter ORM-Frameworks mit Fokus auf ihrem Anwendungspotenzial für Content-Management-Systeme” selbstständig verfasst und keine anderen als die angegebenen Quellen und Hilfsmittel benutzt habe, alle Ausführungen, die anderen Schriften wörtlich oder sinngemäß entnommen wurden, kenntlich gemacht sind und die Arbeit in gleicher oder ähnlicher Fassung noch nicht Bestandteil einer Studien- oder Prüfungsleistung war. Ich verpflichte mich, ein Exemplar der Seminararbeit fünf Jahre aufzubewahren und auf Verlangen dem Prüfungsamt des Fachbereiches Medizintechnik und Technomathematik auszuhändigen.

Name: Ingmar Szmais

Reichshof, den 26.12.2018

Unterschrift des Studenten

1. Prüfer: Prof. Dr. rer. nat. Volker Sander 2. Prüfer: Thomas Joussen Reichshof, 26. Dezember 2018

2

Inhaltsverzeichnis

● 1. Einleitung 4

● 2. Umgebung 5

● 3. Voraussetzung und Einrichtung 6

○ RedbeanPHP 6

○ Doctrine 7

○ Maghead 9

● 4. Erweiterte Nutzung und Performance 11

○ RedbeanPHP 11

○ Doctrine 14

○ Maghead 19

● 5. Fazit 23

● 6. Quellen 27

● 7. Anhang 28

3

1. Einleitung Durch den Fortschritt der globalen Vernetzung und deren Integration in die Gesellschaft werden immer mehr analoge Datenverwaltungssysteme durch digitale Content-Management-Systeme (CMS) ersetzt. Besonders in der Web-basierten CMS Entwicklung sorgt die dadurch steigende Datenmenge und Datenverknüpfung in Korrelation mit der steigenden Komplexität der Anwendungen für Probleme, die sich meist durch eine verbesserte Datenstruktur und Reduzierung trivialer Datenbankabfragen beheben lassen. Besonders die Migration der meist prozeduralen, analogen Daten hin zu objektorientierten digitalen Daten stellt bei der Datenverwaltung eine der größten Schwierigkeiten dar. Die Nutzung von Objektrelationalen Abbildungen (abgeleitet von “object-relational mapping” Abk. ORM) spielt hierbei eine entscheidende Rolle, da sie die Transformation der Daten hin zu einer objektorientierten Datenstruktur an der Datenbankschnittstelle übernimmt und somit an dem Ressourcen-intensivsten Punkt, der Verbindung des Webservers zum Datenbankserver, ansetzt und dabei hilft den Daten-Overhead zu reduzieren. Das primäre Ziel eines dazu genutzten ORM-Frameworks ist es somit eine intelligente Schnittstelle zur Datenbank bereitzustellen, die durch möglichst dynamische Objektrelationen die Abrufe der Datenbank auf eine Minimum reduziert. Zusätzlich sollte sekundär die Semantik des Frameworks intuitiv verständlich sein und gleichzeitig eine hohe Konfigurierbarkeit bereitstellen, um eine fehlerhafte oder Framework-externe Nutzung und somit Gefährdung des primären Ziels zu vermeiden.

4

2. Umgebung Der Vergleich beinhaltet die ORM-Frameworks RedBeanPHP 5.2, Doctrine 2.6 und Maghead 4.0 . Sämtliche Tests werden auf einem Ubuntu 16.04 Betriebssystem mit PHP-Version 7.2, auf einem Nginx-Webserver der Version 1.14.1 und einem MariaDB-Datenbankserver Version 10 ausgeführt. Als Testobjekt für die Datenverwaltung wird ein stark vereinfachtes Modell eines CMS einer Hochschule simuliert. Das Modell enthält 3 inhaltsspezifische Tabellen in Form von 10000 Studierenden, 10 Fachbereichen und 100 Modulen. Je nach Framework enthält es zusätzlich Tabellen für die anfallenden Verknüpfungen zwischen Fachbereichen und Modulen (1 zu N) und Studierenden und Modulen (N zu N). Hierbei werden alle Module mit jeweils einem Fachbereich verknüpft (die Anzahl der Module pro Fachbereich ist hierbei zufällig und kann auch 0 betragen) und jeder Student mit bis zu 6 Modulen, beziehungsweise jedes Modul mit beliebig vielen Studenten .

5

3. Voraussetzungen und Einrichtung RedbeanPHP Unter den verglichenen Frameworks setzt RedBeanPHP 5.2 die wenigsten Abhängigkeiten voraus. So benötigt das Framework lediglich PHP 5.3 oder höher (PHP 6 wird nur teilweise unterstützt), die PHP Datenobjekt-Erweiterung (abgeleitet von “PHP data objects extension” Abk. PDO) und einen der gängigen Datenbanktreiber wie MySQL, MariaDB, PostgreSQL oder SQLite. Zusätzlich kann die Kompatibilität weiterer Treiber durch diverse RedBean Extensions bereitgestellt werden. Die Einrichtung ist nach Bereitstellung der Abhängigkeiten ebenfalls sehr einfach, da das komplette Framework in Form von einer großen PHP-Datei eingeladen wird. Danach ist die komplette Einrichtung des Frameworks fertig, was es unter den hier behandelten Frameworks zu dem Einfachsten und mit einer Dateigröße von < 1MB zum Kleinsten macht. Als Schnittstelle dient hierbei die in der zuvor beschriebenen Datei enthaltene Klasse R, welche über meist statische Aufrufe Daten von der Datenbank abfragt oder persistiert. Um mit der Verwaltung der Daten zu beginnen wird eine Setup-Funktion von R aufgerufen. Dabei erstellt das Framework, sofern die Funktion ohne Parameter aufgerufen wurde, eine eigene temporäre Datenbank, welche zu Entwicklungszwecken genutzt werden kann. Diese wird allerdings nicht für die Nutzung auf Produktiv-Systemen empfohlen, da sie auf mangelnder Wartung Performance- und Sicherheitslücken aufweist. Eine eigene Datenbank für die Nutzung auf Produktiv-Systemen wird nicht grundlegend bereitgestellt. Dafür besteht die Möglichkeit das Framework mit einer bereits vorhandenen Datenbank durch Angabe des Data-Source-Name (DSN) und der Zugangsdaten im Setup-Aufruf zu verknüpfen (siehe Abbildung 1.1). Der DSN übergibt sämtliche Kontaktdaten der Datenbankverbindung innerhalb eines konventionellen Strings. Sobald die Verbindung zur Datenbank gewährleistet ist können Daten abgerufen und persistiert werden. Dies geschieht über die Verwendung von sogenannten Beans. Ein Bean ist ein dynamisch erweiterbares Tabellenschema auf dessen Basis sich alle Grundfunktionalitäten der Datenverwaltung, definiert durch die sogenannten

6

CRUD-Operatoren, realisieren lassen. Die CRUD-Operatoren enthalten die Grundoperatoren einer Datenverwaltung, “create” zum erstellen, “read” zum lesen, “update” zum aktualisieren und “delete” zum löschen. Zum Erstellen einer neuen Datenbanktabelle wird ein Bean per “dispense”-Befehl vorbereitet. Danach können dem Bean beliebig viele neue Attribute hinzugefügt oder bereits bestehende Attribute geändert werden. Sobald die Bearbeitungen des durch den Bean dargestellten Datenbankeintrags beendet ist, kann dieser durch den “store”-Befehl auf der Datenbank persistiert werden, durch welchen man als Rückgabewert die dynamisch erstellte ID des Datenbankeintrags erhält. Durch den “load”-Befehl kann der Eintrag in einen neuen Bean geladen und dort weiterverarbeitet werden. Gelöscht werden kann der Datenbankeintrag eines geladenen Beans per “trash”-Befehl. Zusätzlich zu den vier Grundfunktionen bietet RedbeanPHP zur jeder Funktion die Möglichkeit, per “All”-Suffix ganze Arrays von Beans zu verwalten. Alle genannten Funktionen werden statisch auf der R-Klasse aufgerufen. Optional kann durch eine Umkonfiguration des System auf statische Aufrufe verzichtet werden. [Rdoc] ​

Doctrine Doctrine 2.6 benötigt für die Nutzung immer die LSV (“latest-stable-version”) von PHP, was momentan PHP 7.2 entspricht, ebenfalls PDO, einen gängigen Datenbanktreiber und den PHP-Paketmanager Composer. Bei älteren Versionen von Doctrine 2 liegt die Voraussetzung bei PHP 5.4 und höher (PHP 6 ausgeschlossen). Über den Composer wird folgen durch eine erstellte Composer-Konfiguration Doctrine und das benötigte Yaml-Paket von Symfony geladen. Das Yaml-Paket selbst ist dabei optional und wird durch Nutzung von Doctrine 3 oder durch Änderung der Grundkonfiguration in Doctrine 2 obsolet. Alle für die Datenverwaltung notwendigen Dateien können dann über den integrierten Autoloader eingeladen werden. Sobald dies geschehen ist, kann das Framework zur Datenverwaltung genutzt werden und liegt mit einer Größe von ungefähr 8 MB sowohl von der Komplexität als auch vom Speicherbedarf unter den getesteten ORM-Frameworks im Mittelfeld. Anders als bei RedbeanPHP ist Doctrine sehr objektorientiert strukturiert und bietet schon bei der Einrichtung mehrere Konfigurationsmöglichkeiten. So gibt es im

7

Framework eine Setup-Klasse die sich alleine um die Vorkonfiguration der ORM-Schnittstelle kümmert. Da in Doctrine, im Gegensatz zu RedbeanPHP, die Model-Klassen von ihren zugehörigen Repositories und somit von ihrer Datenverwaltungsebene getrennt definiert werden, benötigt das Framework eine Möglichkeit, die bestehenden autarken Modellstrukturen zu interpretieren. Hierzu verwendet Doctrine Metadaten-Konfigurationen die in drei verschiedenen Formaten angelegt werden können: ● Yaml-Dateien (ab Doctrine 3 nicht mehr möglich) ● XML-Dateien ● Dokumentation in der Model-Klassen selbst. Bei der Auswahl der Metadaten-Konfiguration muss der Pfad der Model-Klassen angegeben werden, wodurch das Framework den Entwickler in eine strikte Ordnerstruktur zwingt. Zusätzlich kann in der Konfiguration ein Entwicklungs-Flag für Testzwecke gesetzt werden, wodurch das Caching teilweise aufgehoben wird um ein schnelleres Testen der Software zu ermöglichen. Nachdem diese Vorkonfigurationen eingerichtet wurden, kann durch die EntityManager Klasse eine Datenbankverbindung erstellt werden. Die Klasse erhält dabei ein Array mit den für die Verbindung wichtigen Daten, wie zum Beispiel DSN-Parametern, und die gespeicherte Vorkonfiguration selbst. Hierbei ist es ebenfalls möglich, eine eigene Datenbank durch Angabe des Pfades zu erstellen (siehe Abbildung 2.2). Um nun neue oder bereits vorhanden Objekte zu verwalten, müssen die Metadaten dieser Objekte je nach vorher ausgewählter Art konfiguriert und zum Datenbankschema hinzugefügt werden. Hierfür stellt Doctrine ein Kommandozeilen-Tool zur verfügung was über eine CLI Konfigurationsdatei (“command line interface”) in der Root-Ebene des Projektes eingerichtet wird. Sobald dieses eingerichtet wurde, lässt sich das Datenbankschema über das framework-eigene Schematool aktualisieren. Nachdem das Schema der Datenbank aktualisiert wurde, können nun Objekte erstellt und in auf Datenbankebene verwaltet werden. Hierzu nutzt Doctrine Funktionen des am Anfang erstellten EntityManager Objektes, wodurch, da es sich hierbei um nicht-statische Funktionen handelt, ohne Probleme auch mehrere EntityManager und mehrere Konfigurationen parallel verwendet werden können. Statt der üblichen

8

CRUD-Operatoren verwendet der EntityManager eine leicht abgewandelte Form. So sind die Operatoren zum Erstellen und Aktualisieren eines Objektes in der “persist”-Funktion zusammengefasst, welche zwischen den beiden durch Überprüfung der Existenz einer ID differenziert, und die Operatoren zum Lesen und Löschen eines Objektes werden durch die Funktionen “find” und “remove” bereitgestellt. Allerdings stellt keiner der genannten Operatoren einen tatsächlichen Operator zur Datenbankverwaltung dar, sondern stellt lediglich Anfragen. Für die Verwaltung der Daten stellt Doctrine zusätzlich einen weiteren Operator durch die “flush”-Funktion zur verfügung. Dieser läd bei Aufruf alle durch die anderen Operatoren gestellten Verwaltungs-Anfragen und fasst diese, sofern möglich, in einer Anfrage zusammen, wodurch die Datenbankanfragen erheblich reduziert und die Performance der Datenbankverwaltung gesteigert werden. [Ddoc] ​

Maghead Für die Nutzung des ORM-Frameworks Maghead 4.0 wird PHP 7 oder höher benötigt sowie ebenfalls PDO, einen gängiger Datenbanktreiber und der PHP-Paketmanager Composer. Neben dem Yaml-Paket von Symfony benötigt Maghead zusätzlich noch weitere Pakete, zum Beispiel Teile der Corneltek Bibliothek und ein Doctrine-Paket, welches allerdings nur für String-Manipulationen genutzt wird und nicht zur Datenverwaltung selbst. Hinzu kommt, dass einige der vorausgesetzten Pakete zum jetzigen Zeitpunkt noch unstable sind, sodass das Framework in der 4. Version nur auf einer Entwicklungs-Stabilitätsstufe geladen werden kann. Sowie schon bei Doctrine können alle benötigten Dateien über einen integrierten Autoloader geladen werden. Das Framework ist durch die benötigten Änderungen in der Composer-Konfiguration, den Entwicklungsstatus und eine Größe von > 50 MB das Komplexeste der behandelten Frameworks. [Mpac] [CCLIpac] [CCDpac] ​ Maghead arbeitet ebenfalls mit einer autarken Setup-Klasse, welche die Konfiguration der Datenbank allerdings über einen eigenen Konfigurations-Loader aus einer Yaml-Datei erhält. In dieser Datei liegen alle Konfigurationen sämtlicher Datenbanken, sowie die CLI-Konfiguration und der Pfad zu den Objektklassen ,beziehungsweise Datenbankschema, was auch den Nutzer von Maghead an die Einhaltung einer strikten

9

Ordnerstruktur bindet. Nach dem Erstellen dieser Konfiguration wird diese über einen Symlink mit dem Framework selbst verknüpft, welcher es ermöglicht, über das integrierte Command-Line-Interface jede konfigurierte Datenbank zu erstellen, neu aufzusetzen oder zu aktualisieren. Im Gegensatz zu Doctrine, welches Objektklassen durch Konfiguration von Metadaten einem Datenbankschema zuweist, erstellt Maghead aus einem konfigurierten Datenbankschema eigene Objektklassen(siehe Abbildung 3.1). In diesen Datenbankschema werden dann die Konfigurationen für die einzelnen Tabellen der Datenbank festgehalten. Nachdem ein solches Schema erstellt wurde, werden durch den CLI-Befehl “schema build” die dazugehörigen Objekte, Repositories und Collections automatisch erstellt und durch den CLI-Befehl “” wird die Tabelle auf der Datenbank eingetragen. Auch hier gibt es durch Setzen eines Flag wieder die Möglichkeit die Datenbank neu aufzusetzen. Nun kann man die erstellten Objekte aufrufen und auf der Datenbank persistieren beziehungweise von der Datenbank laden. Da Maghead über keinen Manager zur Datenbankverwaltung verfügt, werden alle Operatoren auf den jeweiligen Objekten selbst aufgerufen. So kann man durch die statische Funktion “create” eine Objekt der aufgerufenen auf der Datenbank erstellen indem man der Funktion ein Array der passenden Datenbankeinträge übergibt. Durch die Funktion “update” kann das Objekt auf der Datenbank aktualisiert werden, durch diverse “find”-Funktionen kann das Objekt von der Datenbank geladen werden und durch die “delete”-Funktion wird es gelöscht. Neben diesen Grundfunktionen bieten die durch das Schema erstellten Collection- und Repository-Klassen weitere Möglichkeiten, größere Mengen von Objekten des gleichen Typs zu verwalten (siehe Abbildung 3.1). [Mdoc] ​

10

4. Erweiterte Nutzung und Performance RedbeanPHP In der Erweiterten Nutzung von RedBeanPHP steigt die Komplexität der Frameworks relativ zur einfachen Einrichtung. So benutzt Redbean für die Verknüpfung von zwei Objekten spezielle Keywords innerhalb der Attributnamen. Grundlegend wird hierbei zwischen einer “One-to-Many” und einer “Many-to-Many” Verknüpfung unterschieden. Einen Verknüpfung, die eine strikte “One-to-One” Verknüpfung erstellt ist nicht implementiert, kann aber durch die Kombination zweier “One-to-Many” Verknüpfungen über Umwege simuliert werden. Alle von RedbeanPHP angelegten Verknüpfungen werden auf der Datenbank selbst gespeichert, was die unsachgemäße Nutzung der Verknüpfungen über einen Framework-externen Zugriff verhindert und die Persistenz der Abhängigkeiten bei einer Migration der Daten auf ein anderes, kompatibles System gewährleistet. Eine “One-to-Many” Verknüpfung wird durch ein Array von Beans als Attribut einer anderen Bean implementiert. Hierbei erkennt das Framework die Verknüpfung anhand des nach einem strikten Schema aufgebauten Attributs-Bezeichner. Dieser Bezeichner muss für eine Verknüpfung den Bean-Typen des als Attribut übergebenen Arrays gefolgt von dem Keyword “List” haben. Zusätzlich muss der Attribut-Bezeichner bei einer “One-to-Many” Verknüpfung den Präfix “own” tragen um die Art der Verknüpfung zu spezifizieren. Um die Attributnamen richtig interpretieren zu können, wird von der Nutzung von in der Programmierung üblichen Notationen wie der “Camelcase”-Notation auf normalen Attribut-Bezeichnern abgeraten, da diese Notation zur Separierung der Keywords benötigt wird. Sollte dennoch ein Attribut ohne Keyword in dieser Notation persistiert werden, wird dies auf der Datenbank in die übliche Underscore-Notation umgewandelt. Zusätzlich kann durch den Präfix “xown” eine strikte Komposition erzeugt werden, deren Abhängigkeit zum Beispiel das Löschen von Kindern beim Löschen des Elternelements automatisiert. Durch das Setzen des “own” Präfixes wird die Abhängigkeit exklusiv für diese Verknüpfung erstellt und alle Beans des Arrays erhalten die eindeutige ID des übergeordneten Beans als Referenz. Hierdurch wird diese Verknüpfung zu einer unidirektionalen Verknüpfung, da das

11

Elternelement selbst keine direkten, datenbank-internen Informationen über seine Kinder erhält. Eine solche Verknüpfung ist statisch und kann nicht im Nachhinein mit einer weiteren Verknüpfung gekoppelt werden. Zum Erstellen einer “Many-to-Many” Verknüpfung muss zuerst eine eigene Bean als Referenzobjekt für die zu verknüpfenden Beans erstellt werden. Diese Referenz wird dann in beiden zu verknüpfenden Beans innerhalb eines Arrays in eine “List”-Attribut mit dem Präfix “shared” gespeichert. RedbeanPHP erstellt nun eine eigene Tabelle für das Referenzobjekt und zusätzlich zwei Referenztabellen für die Verknüpfungen der ursprünglichen Beans mit deren Referenz-Bean. Dies ermöglicht dem Framework auch Verknüpfungen mit mehr als 2 Objekten beziehungsweise Datenbanktabellen anzulegen. Zusätzlich sind die Verknüpfungen der Referenztabellen ebenfalls wieder strikte Kompositionen, sodass das Löschen eines Objektes automatisch zum Löschen seiner Referenz führt. Die Referenzen müssen somit nicht noch manuell bereinigt werden (siehe Abbildung 1.1). [Rdoc] ​

Des Weiteren bietet RedbeanPHP die Möglichkeit, Objekte mit Objekten desselben Typs zu verknüpfen und somit in einer Tabelle rekursiv verknüpfte geschlossene Gruppen zu erzeugen. Dadurch lassen sich innerhalb einer Tabelle komplexe, rekursive Baumstrukturen verwalten. Des Weiteren stellt das Framework eine Funktion zum direkten Duplizieren von Beans mit allen dazugehörigen Verknüpfungen zu Verfügung,

12

diverse Import und Export Funktionen, mit denen sich Beans direkt aus standardisierten Requests (wie zum Beispiel POST) erstellen lassen und diverse Interaktionsmöglichkeiten über Präfixe und Konstanten. Zum Testen der Performance wurde das oben genannte Datenbankmodell zunächst nur unter Verwendung der Grundfunktionalitäten erstellt. Durch den Mangel an Grundfunktionen zum zentralisierten Erstellen und Speichern kommt das Framework hierbei zu einer Laufzeit von 407 Sekunden zum Erstellen des kompletten Modells inklusive sämtlicher Verknüpfungen, wobei davon ungefähr 80% der Laufzeit für die Verknüpfung der Studenten mit den Modulen benötigt wird. Durch die Nutzung der erweiterten Funktionalitäten und die dadurch entstehende Umstrukturierung des Programmcodes lässt sich diese Laufzeit um ca. 40% auf 232 Sekunden verbessern, wobei die Verbesserung der Laufzeit auf das Entfernen redundanter “load”- und “store”-Operatoren zurückzuführen ist und nicht etwa auf eine Verbesserung der Performance der erweiterten Funktionen durch zum Beispiel Caching. So haben weitere Tests ergeben, dass Funktionen wie zum Beispiel “storeAll” keinen Vorteil der Effizienz durch zusammenfassen der Persistierunganfragen bringen, sondern lediglich die Lesbarkeit des Programms durch Auslagern einer Schleife verbessern (siehe Abbildung 1.2). Zur weiteren Verbesserung der Performance bietet RedbeanPHP eine ungesicherten “Freeze”-Modus, der für nicht-initiale Anfragen verwendet werden kann. Während der normale Modus des Frameworks bei jeder Persistierungsanfrage die Datenbankstruktur auf Kompatibilität zu dieser Anfrage überprüft und gegebenenfalls neue Tabellen hinzufügt oder Tabellen um einzelne Attribute erweitert, wird im “Freeze”-Modus eine Exception geworfen. Dadurch eignet sich dieser Modus nicht für die initiale Entwicklung, da er die Datenbank nicht mehr dynamisch erweitern kann, jedoch kann man nach der endgültigen Fertigstellung der Datenbankstruktur dadurch die Performance des Programms verbessern. Somit funktioniert die realitätsnahe Nutzung des Modus analog zu der eines Frameworks mit vorkonfigurierter Datenbank, da zuerst ein einzelnes, komplettes Modell im normalen Modus in erstellt wird, das von diesem interpretiert und in eine zeitgleich erstellt Datenbanktabelle eingepflegt wird, welches darauf direkt wieder gelöscht wird. Danach wird der Modus geändert und die

13

Datenbanktabelle kann wie im normalen Modus genutzt werden. Die Erst-Initialisierung wird je nach Konvention in eine “Setup” PHP-Datei oder ähnlich ausgelagert, die dann zur initialen Vorkonfiguration dient. Durch das Setzen des Modus erzielt RedbeanPHP bei der Erzeugung des Datenbankmodells bei Nutzung der Grundfunktionen eine Laufzeit von 191 Sekunden und unter Nutzung der erweiterten Funktionalitäten eine Laufzeit von 142 Sekunden. Somit erreicht das Framework in diesem Modus auf nahezu allen “store”-Anfragen eine Performance-Steigerung von bis zu 200%, welches den Unterschied zu der Performance anderer ORM-Frameworks allerdings nicht ausgleichen kann. Besonders das Erstellen der Verknüpfung zwischen den Studenten und den Modulen erweist sich in allen Fällen durch den notwendigen Aufbau von drei Tabellen als sehr aufwendig, aufgrund der dynamischen Erweiterbarkeit der “Many-to-Many”-Verknüpfung um weitere Tabellen. Da die beiden Verknüpfungen somit in keiner direkt interpretierbaren Beziehung stehen können sie nicht innerhalb eines Datenbankaufrufes erstellt werden, sondern müssen innerhalb von zwei beziehungsweise drei separierter Aufrufen erstellt werden. Diese können auch in der erweiterten Nutzung nicht zusammengefasst werden. [Rdoc] ​

Doctrine Wie bereits erwähnt ist für die Nutzung von Doctrine die vorherige Implementierung der betreffenden Objektklassen und deren Konfiguration über Metadaten erforderlich. Zur Darstellung des Test-Modells der Seminararbeit wurde eine Konfiguration über die Dokumentationsblöcke der Klassen selbst benutzt, da diese nicht so aufwendig und weniger fehleranfällig ist wie die Konfiguration über XML und die Konfiguration über YAML als veraltet markiert wurde und mit der nächsten Version nicht mehr unterstützt wird. Die Nutzung von XML-Konfigurationen ermöglicht, zusätzlich zu allen Funktionalitäten der Dokumentations-Konfiguration die Möglichkeit eine Objektklasse auf mehrere Datenbanktabellen zu mappen und ihr somit eine mehrdeutige Semantik zu verleihen. Für die Konfiguration durch Dokumentation werden nach dem Erstellen der Objektklassen in deren Dokumentationen bestimmte Keywords eingefügt, die durch den Präfix “@” gekennzeichnet werden, durch welche das Schematool von Doctrine ein

14

interpretierbares Datenbankschema erzeugt. Die Umgebung der behandelten Objektklasse wird mit dem Keyword “@Entity” definiert wird daher direkt über der Definition des Klassen-Scopes in einen Dokumentationsblock eingefügt. Um das Objekt mit einer Tabelle zu assoziieren wird zusätzlich das Keyword “@Table()” angehangen wo innerhalb der Klammern das Attribute “name” gesetzt wird. Optional kann hier ebenfalls ein nicht standardisierter Index und Einschränkungen mitgegeben werden. Sobald so der Bereich und die Datenbankassoziation der Objektklasse definiert wurden, können über den Parametern der Klasse die Datenbankparameter konfiguriert werden. Hierbei ist es nicht zwingend erforderlich, dass die Verknüpfung der Datenbank surjektiv ist. So kann das Objekt auch Parameter enthalten die nicht über das Datenbankschema persistiert werden. Ein Datenbankparameter wird über das Keyword “@JoinColumn()” erzeugt, welches als Attribut, neben dem obligatorischen “type”, optional jede weitere Spaltenkonfiguration einer gängigen Datenbank erhalten kann. Des Weiteren kann durch das Keyword “@id” der Parameter als Datenbank-Identifier markiert und durch das Keyword “@GeneratedValue” dieser Identifier generiert werden. Hierbei kann durch die Übergabe eines Strategy-Attributs eine andere Generierungmethode als die standardisierte automatische Inkrementierung ausgewählt werden. Neben diesen hier genannten Keywords gibt es noch weitere, die zur besseren Handhabung in spezifischen Fällen beitragen. Die Definition der Verknüpfungen wird in Doctrine ebenfalls über die Dokumentation festgelegt. Hierbei bietet Doctrine die Möglichkeit jede beliebige Verknüpfung als unidirektional, bidirektional oder selbstreferenzierend zu definieren. Eine Verknüpfung besteht dabei immer aus einer Kombination aus einem Typisierungs-Keyword, welches die je nach Art der Verknüpfung definiert wird, und aus einem Join-Keyword, welches die verknüpfenden Spalten definiert. Die einfachste darstellbare Verknüpfung ist eine unidirektionale “One-to-One”-Verknüpfung. Hierbei erhält die verwaltende Klasse auf dem für die Verknüpfung definierten Parameter das gleichnamige Keyword “@OneToOne()”, welches im Attribut “targetEntity” den Namen der zu verknüpfenden Klasse erhält. Zusätzlich dazu erhält die verwaltende Klasse ebenso das Keyword “@JoinColumn()”, welches wiederum als Attribute die Namen der Spalten der Datenbank enthält, die die

15

Verknüpfung identifizieren. Solch eine Verknüpfung kann auch selbstreferenzierend sein, indem der Name der verknüpfenden Klasse auf die zu verwaltende Klasse gesetzt wird. Diese Art der Verbindung kann auf eine bidirektionale Verknüpfung erweitert werden indem die zu verknüpfende Klasse ebenfalls um einen Parameter erweitert wird, der das Typisierungs-Keyword erhält. Des Weiteren müssen beide Klassen in dem Typisierungs-Keyword um das Attribut “mappedBy ”oder “inversedBy” erweitert werden, in denen jeweils der Name des verknüpfenden Parameters der anderen Tabelle definiert wird. Beide Klassen dürfen dabei nicht dasselbe Attribut haben, allerdings ist es bei der “One-To-One”-Verknüpfung für die Nutzung, egal welche Klasse zuordnet und welche Klasse invertiert. Zusätzlich ist es ebenfalls über Umwege möglich über einen weiteren Parameter eine bidirektionale, selbstreferenzierende “One-To-One”-Verknüpfung zu definieren (ähnlich zu einer ungeordneten Menge an doppelt-verketteten Listen). Die Erstellung einer unidirektionalen “Many-To-One”-Verknüpfung erfolgt komplett analog zu der Erstellung einer unidirektionalen “One-To-One”-Verknüpfung mit Ausnahme der Änderung des Keywords gleichnamig zu Verknüpfung zu “@ManyToOne”. Durch die Änderung des Keywords wird dann lediglich Framework-intern die Injektivität der verknüpfenden Referenzen entfernt, sodass auch mehrere Verknüpfungen auf das auf den selben Eintrag referenzieren können. Die Verknüpfung referenziert immer von der “Many”- Tabelle zur “One”-Tabelle. Einer direkte “One-To-Many” Verknüpfung über ein Keyword gibt es in Doctrine nicht. Dies kann zwar durch Umwege erzeugt werden, meist ist allerdings die Nutzung einer “Many-To-Many”-Verknüpfung unter Verwendung von speziellen Einschränkungen einfacher zu implementieren und ausreichend performant. Die bidirektionale Version dieser Verknüpfung wird durch eine “One-To-Many”-Verknüpfung implementiert. Hierbei erfolgt die Implementierung, wie schon bei der unidirektionalen Alternative, analog zu der der ”One-To-One” -Verbindung mit der Ausnahme des Ersetzens des Typisierungs-Keywords durch “@OneToMany”. Da Doctrine für die Verwendung von Parametern, die mehrere Objekte enthalten, nicht die standard PHP-Arrays sondern, aufgrund der spezifisch besseren

16

Nutzbarkeit, eigene, framework-interne Array-Collections benutzt, muss der Parameter auf der “One”-Tabelle im Konstruktor mit eben so einer Collection gesetzt werden. Auch hier ist es möglich, über einen weiteren Parameter eine bidirektionale, selbstreferenzierende Verknüpfung zu erzeugen. Die Vertauschung der Worte im Keyword entsteht hier durch die in vielen Anwendungsbereichen konventionelle, standardisierte Bezeichnung “One-To-Many” für eine gewichtete zweidimensionale Verknüpfung. Gegensätzlich dazu wird bei der unidirektionalen Variante aufgrund des deutlich höheren Anwendungsbedarfes der Referenz von der “Many”-Tabelle auf die “One”-Tabelle die Verwendung von “Many-To-One” als Standard genutzt. Somit bildet die unidirektionale Verknüpfung im Keyword die Ausnahme von der Regel. Zur Erstellung einer unidirektionalen “Many-To-Many”-Verknüpfung wird ebenfalls das gleichnamige Typisierungs-Keyword “@ManyToMany” zur Definition genutzt und die betroffenen Referenz-Parameter werden wieder im Konstruktor der Klasse mit einer Array-Collection gesetzt. Allerdings wird bei “Many-To-Many”-Verknüpfungen kein “@JoinColumn()” Keyword, sondern ein “@JoinTable()” Keyword benutzt, das den Namen einer zunächst virtuellen Verknüpfungstabelle als Attribut bekommt. Aus diesem erstellt Doctrine dann beim Aktualisieren durch das Schematool eine eigene Tabelle ohne Objektklasse, die in jedem Eintrag neben der eigenen Id jeweils eine Id der verknüpften Tabellen enthält, wodurch die einzelnen Verknüpfungen zugeordnet werden. Als zusätzliche Attribute werden bei der unidirektionalen Verknüpfung beide zu verknüpfenden Spaltentupel der verwaltenden Klasse übergeben, sodass die verknüpfte Klasse bis auf die Bereitstellung dieser Parameter nicht konfiguriert werden muss. Somit ermöglichen die unidirektionalen Verknüpfungen in Doctrine ebenfalls die Anbindung an eine framework-externe Modellstruktur, ohne diese verändern zu müssen. Auch hier kann durch eine klasseninterne Struktur eine unidirektionale, selbstreferenzierende Verknüpfung erzeugt werden. Bei der bidirektionalen “Many-To-Many”-Verknüpfung wird wiederum das Typisierungs-Keyword mit der Zielklasse und den Attributen “mappedBy” oder “inversedBy” in beiden Klassen gesetzt. Zusätzlich wird in der zuordnenden Klasse in dem Keyword “@JoinTable()” ebenfalls der Name einer virtuellen Verknüpfungstabelle angegeben (siehe Abbildung 2.1). [Ddoc] ​

17

Die Performance des Frameworks ist dabei stark abhängig von der korrekten Konfiguration der Tabellen und noch stärker von dem Zeitpunkt der tatsächlichen Persistierung. So wurde eine Version des oben genannten Datenbankmodells konstruiert, in der direkt nach jeder Persistierungsanfrage diese per “flush()”-Operator mit der Datenbank synchronisiert wird. Dadurch entstehen beim Modell ungefähr 25000 Aufrufe des Operators. Hierbei wurde die Konstruktion während der Laufzeit nach ungefähr 1.000 Sekunden bei unter 25% Fortschritt abgebrochen, wodurch sich eine Laufzeit von mehr als 4.000 Sekunden approximieren lässt. Durch das Reduzieren der “flush()”-Operatoren auf einen nach der Erstellung aller Objekte und einen nach deren Verknüpfung, erreicht man eine deutlich verbesserte Laufzeit von 5 Sekunden, wobei neben der tatsächlichen Persistierung das Suchen der Objekte den größten Zeitaufwand in Anspruch nimmt. Durch das Zwischenspeichern der Objekte und die dadurch Entstehende Reduzierung der Suchanfragen und die Reduzierung auf einen “flush()”-Operator lässt sich hier nochmals fast die hälfte der Laufzeit sparen. Die Nutzung des Zwischenspeichers wird hierbei jedoch stark erhöht. Diese drastische Performance-Steigerung lässt sich durch die Struktur des “flush()”-Operators erklären, da dieser durch seinen Aufruf (durch unter anderem die Nutzung von Doctrines UnitOfWork) zunächst eine sehr komplexe und aufwendige

18

Initialisierungszeit besitzt, da sämtliche zur Persistierung angefragten Daten zunächst auf Änderung und Korrelation mit anderen Daten überprüft werden. Folgend kann der Operator allerdings durch die gesammelten Informationen die Anzahl der Datenbankanfragen durch Zusammenführen und Löschen redundanter Anfragen (wie zum Beispiel dem Ändern eines im gelöschten Eintrags) effizient reduzieren. Dadurch erzielt er schon bei wenigen Persistierungsanfragen eine höhere Performance als das direkte Speichern ohne Framework. Folgend ist anzunehmen, dass die relative Performance-Steigerung zu direkt-speichernden Frameworks (wie zum Beispiel RedbeanPHP) mit steigender Anzahl von Datensätzen korreliert. Zusätzlich ist zu erwähnen, dass das getestete Datenbankmodell durch seine Struktur das Framework Doctrine besonders begünstigt. So gibt es wenig realistische Anwendungsfälle im Content-Management, wo ein tatsächliches Synchronisieren der Datenbank erst nach 10000 Persistierungsanfragen notwendig ist, da die meisten autarken Operationen in einem CMS kleinere Anfragemengen (ungefähr bis zu 30) bis zum Persistierungspunkt erstellen. Wenn man das Framework nun dahingehend umstellt, eine “flush()”-Operation nach jeweils ungefähr 30 Einträgen durchzuführen erhält man eine Laufzeit von 102 Sekunden. [Ddoc] ​

Maghead Die Einrichtung von Maghead erfolgt im Gegensatz zu den anderen Frameworks, sehr analog zu der manuellen Einrichtung eines Datenbanksystems. So setzt das Framework grundlegende Kenntnisse über die Datenbank voraus. Es wird bei Maghead keine Objekte-interpretierende Vorkonfiguration erstellt, sondern eine Schema-interpretierende Vorkonfiguration. Hierzu werden die Datenbankschema in einem in der Grundkonfiguration festgelegten Ordner implementiert. Jedem Schema wird dabei die Klasse “DeclareSchema” vererbt, welche die Grundfunktionen der Schema bereitstellt. Zudem wird eine öffentliche Funktion “schema()” implementiert, in der die Datenbankstruktur der zugehörigen Tabelle durch Aufrufen dynamischer Funktionen definiert wird. In dieser Funktion kann nun zuerst der Tabellenname über die Funktion “table()” definiert werden. Sofern dieser nicht gesetzt wird, wird hierfür der Plural des Schemanamens in konventioneller Datenbankschreibweise genommen (zum

19

Beispiel wird aus ‘SubjectAreaSchema’ ‘subject_areas’). Danach werden einzelne Spalten der Datenbank über die Funktion “column()” definiert, die den Namen der Spalte als Attribut erhält. An diesem Funktionsaufruf können nun beliebig viele weitere Einschränkungen aufgerufen werden, an welchen wiederum neue Einschränkungen aufgerufen werden können. Konventionell bezieht sich die erste dieser Einschränkungen meist auf eine Typisierung der Spalte, was zum Beispiel durch den Aufruf der “integer()”-Funktion passiert. Je nach Typisierungs-Funktion lassen sich nun weitere Funktion anhängern wie zum Beispiel “unsigned()” zur Definition eines positiven Integers oder “autoIncrement()”, um diesen Wert automatisch inkrementieren zu lassen. Anhand dieser Einschränkungen wird dann bei der Erstellung über die CLI das Modell, das Repository und die Collection des Objektes erstellt, welche diesbezüglich dann weitere Zusatzfunktionalitäten bereitstellen. Des Weiteren erstellt Maghead automatisch eine Meta-Tabelle in der das Framework Daten wie Migrationszeitpunkte oder das Erstellungsdatum der Datenbank festhält. Nachdem die Spalten der Datenbanktabellen definiert wurden können nun Verknüpfungen anhand dieser Spalten erstellt werden. Hierbei unterscheidet sich Maghead in dem Punkt von anderen Frameworks darin, dass auch die Referenzspalten manuell vom Entwickler erstellt werden müssen. So wird vermieden dass eine spezielle Datenbankkonfiguration durch eine automatisierte, dem Entwickler unbekannte Funktionalität beschädigt wird. Des Weiteren gibt es in Maghead keine zusammenhängenden bidirektionalen Verknüpfungen, da jedes Schema autark unidirektionale Verknüpfungen erstellt, in denen es lediglich die Existenz des zu verknüpfenden Schemas und der passenden Referenzspalte überprüft. Eine unidirektionale “One-To-One”-Verknüpfung wird somit unterhalb der Spaltendefinition durch den dynamischen Funktionsaufruf “belongsTo()” erstellt. Dieser erhält als ersten Parameter einen eigens für die Verknüpfung definierten Namen, sowie folgend den Schemapfad des zu verknüpfenden Schema und die Namen der referenzierenden Spalten. Hierbei kann durch die Angabe von nur einer Referenz-Spalte eine selbstreferenzierende Verknüpfung auf die eigene Id erzeugt werden. Die hierzu genutzten Referenz-Spalten müssen wie erwähnt selbst erstellt werden. Ursprünglich

20

wurde hierzu die Funktion “one()” benutzt, welche aber im momentane Entwicklungsstand nicht verfügbar ist. Eine unidirektionale “One-To-Many”-Verknüpfung wird analog dazu mit der Funktion “many()” und den gleichen Parametern erstellt, allerdings in anderer Reihenfolge. Die Verknüpfung wird dafür in der “One”-Tabelle angelegt. Um einer bidirektionale Verknüpfung zu simulieren, muss zusätzlich eine passende “One-To-One”-Verknüpfung in der verknüpften Tabelle angelegt werden. Für eine unidirektionale “Many-To-Many”-Verknüpfung muss zunächst manuell eine Verknüpfungstabelle über ein eigenes Schema angelegt werden, die Referenz-Spalten für die zu verknüpfenden Tabellen enthält. Nun werden in dieser Verknüpfungstabelle unidirektionale Verknüpfungen zu den beiden Zieltabellen erstellt. Danach wird in der Ursprungstabelle der unidirektionalen Tabelle eine “One-To-Many”-Verknüpfung zu der Referenztabelle erstellt. Nun bietet Maghead die Möglichkeit, über die dynamische Funktion “manyToMany()” aus dem Zusammenzuführen zweier Verknüpfungen eine weitere zu erstellen. Hierbei wird als erster Parameter wieder ein eigener Verknüpfungsname übergeben. Als weitere Parameter werden zunächst der Name der “One-To-Many”-Verknüpfung, die vom aktuellen Schema ausgeht, gefolgt von dem Namen der “One-To-One”-Verknüpfung der Referenztabelle die durch die erste Verknüpfung definiert wurde. Hierbei erstellt Maghead jetzt einer Verknüpfung von Verknüpfungen. Die Funktionalität lässt sich beliebig dynamisch um weitere Verknüpfungsebenen erweitern (siehe Abbildung 3.1). [Mdoc] ​

21

Zusätzlich zu diesen Funktionalität bietet Maghead mit Abstand die meisten zusätzlichen Funktionen in denen das Framework Standardprozeduren einer Anwendung übernimmt. Unter anderem stellt es die Möglichkeit zur Verfügung plattformspezifische Schema anzulegen die nur für spezielle Datenbanktypen genutzt werden, was man durch den Tag “@platform” in der Dokumentation eines Schemas bestimmen kann. Des Weiteren ist es möglich, über die möglichen optionalen Einschränkungen der Datenbank hinaus, eigenen Validatoren für Datenbankfelder zu definieren, die beliebig komplex werden dürfen. Dafür muss die Funktion “validator()” auf der definierenden “column()”-Funktion aufgerufen werden. Innerhalb der Parameter der Funktion kann ein beliebiger Validator als Funktion definiert werden. Außerdem können über die erstellten Collections eines Schemas komplexe, tabellenübergreifende Filter als eigene Objekte erstellt werden. Maghead erzielt beim Test der Performance durch das zugrundeliegende Datenbankmodell eine Laufzeit von 70 Sekunden, wovon 50 Sekunden für die tatsächliche Persistierung von Daten verwendet werden und 20 für das Laden von Daten. Wenn man nun die Ladeaufrufe durch Verwendung von Systemspeicher reduziert, erhält man eine Laufzeit von 50 Sekunden. Damit ist Maghead zwar langsamer als Doctrine, was allerdings mit dessen geringer Anzahl von Persistierungen zu begründen ist. So bietet Maghead unter dem Aspekt der Laufzeit pro Persistierung eine deutlich höhere Performance als die anderen beiden Frameworks. [Mdoc] ​

22

5. Fazit Durch die unterschiedliche Handhabung und Komplexität der behandelten ORM-Frameworks lassen sich bei jeden Framework eindeutige Vor- und Nachteile erkennen, welche sie für ein für spezifisches Arbeitsumfeld geeignet erscheinen lassen, sie aber für andere nicht ausschließen. So eigenet sich RedbeanPHP 5.2 durch seine besonders einfache Konfiguration, seine geringe Größe und Kompatibilität mit früheren PHP Versionen besonders für kleine, ältere Installationen. Zuzüglich dazu ermöglicht die einfache und verständliche Konfiguration der Datenbankverwaltung eine gute Integration in bereits existierende Systeme ohne ORM-Framework. Hierbei kann die Integration auch vorerst partiell erfolgen, da im Framework selbst kaum semantische Konventionen vorgegeben sind sodass es sich auch teilweise implementieren lässt ohne dabei einen durch mangelnde Abgeschlossenheit auftretenden Fehler zu verursachen. Zusätzlich ist der Programmfluss innerhalb der Nutzung der Grundfunktionalitäten leicht lesbar und von der Struktur sehr minimal, da das Framework eine sehr strikte Konvention zur Benennung der Attribute vorgibt. Dadurch lassen sich im Gesamtkonzept des Programms viele Diskrepanzen vermeiden und die Dokumentation wird dadurch für einen fortgeschrittenen Programmierer gut verständlich. Allerdings stellte diese strikte Konvention der Notation der Attribute und Typen bei der erweiterten Nutzung ebenfalls eine große, semantische Hürde dar, was allerdings kein schwerwiegender negativer Faktor ist, da sich das Framework aufgrund seiner hohen Laufzeiten sowieso nicht für den gebrauch großer komplexer Datenbanksysteme eignet. Durch seine geringe Performance und teilweise veraltete Code-Konvention eignet es sich desweiteren nicht für neue, größere Projekte, da die meisten Funktionalität aufgrund ihrer Abwärtskompatibilität nicht auf dem aktuellsten Konventionsstandard sind. Somit können hohen Anforderungen an das System durch die mangelnde Performance des Frameworks zu einem Flaschenhals führen. Des Weiteren ist es mit der Nutzung erweiterter Funktionalitäten und dem “Freeze”-Modus nahezu genauso anfällig für Fehler wie andere Frameworks. Außerdem erschwert die Komprimierung sämtlichen Codes in einer Datei die Wartbarkeit und das generelle Verständnis des Frameworks.

23

Generell eignet sich das Framework somit eher für die anfängliche Entwicklung als für die Effiziente Nutzung auf Live-Systemen. [Rdoc] Doctrine 2.6 eignet sich hingegen durch seinen aktuellen Entwicklungsstand sehr gut für neuere Installationen und Live-Systeme, wobei seine Dokumentation selbst für Programmierer mit wenig PHP-Erfahrung sehr gut verständlich ist, was seine etwas komplexere Einrichtung ausgleicht. Hierbei muss allerdings auf die Art der Datenverwaltung geachtet werden. So kommt es bei Systemen mit einer öffentlichen Datenverwaltung durch Nutzer einer Website häufig zu wenig Persistierungsanfragen pro “flush()”-Operator, da das System sehr schnelllebig ist und dementsprechend häufig synchronisiert werden muss (zum Beispiel durch automatisierte Speicherung in einem Web-Text-Editor oder eine asynchrone Kommentarfunktion), was die Effizienz des Systems stark beeinträchtigt. Bestens eignet es sich hingegen für geschlossene Datenverwaltungen durch wenige, ausgewählte Administratoren oder durch das System selbst (zum Beispiel durch CRON-Jobs), da hierbei durch Absprache nicht unbedingt alle Daten aus allen zugreifenden System simultan aktuell gehalten werden müssen. Desweiteren ermöglicht die hohe Konfigurierbarkeit über das Command-Line-Interface eine einfache, sprachunabhängige Bedienung. Durch die Nutzung einer konventionellen Ableitung des CRUD-Operatoren-Systems wirkt das System zwar anfänglich komplex was es allerdings durch die einfache Nutzung der eigenen Operatoren und ausführliche Dokumentation ausgleicht. Zusätzlich sorgen eben diese Operatoren für die hohe Performance, die schon durch die Grundeinrichtung der Frameworks gegeben ist und nicht zusätzlich später noch erweitert werden muss. Das Framework selbst ist dabei sehr anwendungsorientiert geschrieben und dokumentiert, sodass auch in der erweiterten Nutzung die Anwendungsfälle mit der höchsten Nutzbarkeit meist den Standard darstellen. Durch die hohe, dynamische Konfigurierbarkeit entsteht allerdings auch der Nachteil, dass die Wartbarkeit besonders für nicht fortgeschrittene Programmierer sehr gering ist, da das Framework unter anderem durch seine 3 Grundkonfigurations-Methoden bei gleicher Konfiguration nahezu keinen Wiedererkennungswert haben kann, was die Kommunikation im Pair-Programming auch bei zwei erfahrenen Doctrine-Entwicklern erschweren kann, sofern diese nicht dieselbe Konfigurationsmethode nutzen. Zusätzlich erschwert die schnelle Entwicklung

24

in Kombination mit der dynamischen Konfiguration die Definition von Standards und die Normierung. [Ddoc] ​ Maghead 4.0 eignet sich am besten für erfahrene Entwickler mit guten Kenntnissen in SQL, da das Framework sich durch seine sehr Anfänger-unfreundliche Dokumentation stark von den anderen Frameworks unterscheidet. So sind Teile der Dokumentation (welche sich nach Angaben der Entwickler immer noch unter “heavy development” befindet) unvollständig und setzen ein Grundverständnis der Materie voraus. Somit erleichtert Maghead dem Entwickler nicht das Erstellen einer strukturierten Datenbank, sondern verbessert deren Effizienz durch Bereitstellung sehr vieler spezifischer Funktionalitäten. Des Weiteren ermöglicht es die Verwaltung sehr großer komplexer Datensysteme, die auch über mehrere Datenbanken oder Datenbankserver hinausgehen können und erzielt trotz dieser Komplexität immer noch sehr performante Ergebnisse in kleineren grundlegenden Datenbankabfragen. Daher eignet sich das Framework sowohl für mittelgroße offene Verwaltungssysteme mit einer hohen Anzahl von Zugriffen unterschiedlicher Parteien, da es die performanteste Direkt-Persistierung bietet, als auch für beliebig große Verwaltungssysteme mit beliebigen Spezifikationen, da man durch die vielen optionalen Möglichkeiten des Frameworks nahezu jede komplexe Anfrage performant gestalten kann. Für kleine Systeme ist es hingegen nicht zu empfehlen, da die Komplexität und die Einarbeitung relativ zur gesamten Entwicklungszeit eines kleinen System zu hoch ist und es hierbei, bis auf spezielle Fälle, keinen nennenswerten Vorteil zu den anderen Systemen bietet. [Mdoc] ​

25

RedBean Doctrine Maghead

Komplexität -einfach einzurichten -sehr gut dokumentiert -keine vereinfachte -intuitiv -sehr aktuell Implementierung -bei erweiterter -hoher -unvollständige Nutzung tlv. schlecht Initialisierungsaufwand Dokumentation dokumentiert -keine strikte -setzt Grundverständnis Konfiguration voraus

Performance -sehr gering -tlw. sehr hoch -sehr hohe -keine performanten -starke Varianz je nach Grundperformance Alternativmethoden Einrichtung -sehr geringe Varianz

Wartbarkeit/ -zentralisiert -über Symfony gut -strikte Konfiguration Erweiterbarkeit -Codestruktur erweiterbar -gut intern erweiterbar veraltet/unverständlich -sehr dynamische durch eigene Funktionen Konfiguration -gute Codestruktur

26

6. Quellen [Rdoc] RedbeanPHP Dokumentation seit 2009 von Gabor de Mooij: ​ ​ https://redbeanphp.com (letzter Zugriff 9.12.2018)

[Ddoc] Doctrine 2 Dokumentation seit 2010 von Konsta Vesterinen: https://www.doctrine-project.org/projects/doctrine-orm/en/2.6 (letzter Zugriff 12.12.2018)

[Mpac] Maghead Paketverwaltung seit 2012 von Yo-An Lin: ​ https://packagist.org/packages/maghead/maghead (letzter Zugriff 3.12.2018)

[CCLIpac] Corneltek Command-line framework for PHP Paketverwaltung seit 2012 von ​ ​ ​ Yo-An Lin: https://packagist.org/packages/corneltek/cliframework (letzter Zugriff 3.12.2018)

[CCGpac] Corneltek PHP Code Generation Library Paketverwaltung seit 2014 von Yo-An ​ ​ ​ Lin: https://packagist.org/packages/corneltek/codegen (letzter Zugriff 3.12.2018)

[Mdoc] Maghead Dokumentation seit 2012 von Yo-An Lin: ​ https://github.com/maghead/maghead (letzter Zugriff 14.12.2018)

[RN] Liste von Zufallsnamen für die Testkonfiguration 2012 von Dominic Tarr: ​ https://github.com/dominictarr/random-name (letzter Zugriff 24.11.2018)

27

7. Anhang (Abbildung 1.1) Performance-Test bei RedbeanPHP (standard mit freeze):

28

(Abbildung 1.2) Performance-Test bei RedbeanPHP (optimiert mit freeze):

29

(Abbildung 2.1) Konfiguration eines Models in Doctrine (am Beispiel Module): ​

30

(Abbildung 2.2) Performance-Test bei Doctrine (2 Flushes):

31

(Abbildung 3.1) Konfiguration eines Schemas in Maghead (am Beispiel Module): ​

32

(Abbildung 3.2) Performance-Test bei Maghead:

33