How to build a REST API v2.0
Nach meinem letztjährigen Beitrag wissen wir, wie eine API auf Basis von Node.JS umgesetzt wird. Da dieses Framework allerdings nur auf eigenen Server oder auf kostenpflichtigen Cloud-Diensten wie die Google Cloud Compute Engines oder Amazon AWS EC2 funktionieren, war es mein Ziel, eine einfachere und vor allem kostengünstigere Variante mit PHP zu realisieren.
Was sind die Voraussetzungen?
Um eine API mit PHP umzusetzen, kann in den meisten Fällen auf das bereits bestehende Hosting-Paket der eigenen Domain zurückgegriffen werden. Die gängigsten Anbieter wie zum Beispiel Hosttech, Hostpoint oder Cyon verwenden prinzipiell Apache als Webserver, mit welchem das nachfolgende Konzept problemlos funktioniert.
Damit kein Durcheinander mit Haupt-Domäne und der API-Schnittstelle entsteht, ist es empfehlenswert, eine neue Subdomain als Zugriffspunkt zu erstellen (zum Beispiel: api.domain.ch).
Was ist der grundlegende Aufbau einer REST API?
Wie bei einem MVC (Model-View-Controller) wird bei einer API eine initiale Route festgelegt, auf welche der Zugriff erfolgt. In einem weiteren Schritt wird ein Controller benötigt, welcher die jeweiligen Anfragen nach CRUD selektiert und an die jeweilige Stelle weiterleitet. An diesem Punkt können die in der Anfrage mitgegebenen Daten in der URL oder aus dem Body an die Datenbankabfrage im Model-Teil (bzw. in meinem Beispiel im Gateway) übergeben werden. Die Antwort aus dieser Abfrage wird wiederum im Controller in das übliche JSON-Format konvertiert und an die Abfragestelle zurückgesendet.
Um die umständlichen «/» aus der URL zu entfernen, werden nebst der Festlegung der Route auch diese Konfiguration im .htaccess im Rout-Verzeichnis der API festgelegt.
Realisierung der API mit PHP
Für die Umsetzung und Versionsverwaltung habe ich mit der Open-Source Software GitHub gearbeitet, auf welcher ich die fertige API auch veröffentlicht habe.
Wie bereits im Aufbau beschrieben, wird im .htaccess zuerst die Route festgelegt:
Im index.php werden die einzelnen Verbindungen zur Datenbankkonfiguration sowie zum Controller geladen und die URL nach den erforderlichen Daten gesplittet sowie auf allfällige Fehler überprüft.
Der darauf aufgerufene Controller selektiert die Anfrage mit der Switch-Case Funktion nach der im Header mitgegebenen Anfrage-Type (also GET, POST, PUT oder DELETE) und ruft die damit verbundene Funktion auf.
Sofern zum Beispiel alle Lizenzen abgerufen werden sollen, wird die Funktion getAllLicenses() aufgerufen. Welche die Anfrage an den Gateway, also den Zugangspunkt zur Datenbank mit den benötigten Daten, in diesem Fall jedoch keine (es werden alle Lizenzen benötigt), weiterleitet.
Mit einem grundlegenden Select-Statement können die Daten im Gateway anschliessend aus der Datenbank ausgelesen und via Controller wieder an die Anfragestelle zurückgeschickt werden.
Anwendung in einer Produktivumgebung
Die in diesem Beispiel gezeigte API ist soweit vollumfänglich funktionstüchtig und könnte genau so auch in einer produktiven Umgebung eingesetzt werden. In einem grösseren, wichtigeren und komplexeren Umfeld ist davon jedoch abzusehen, da es schnell sehr unübersichtlich werden und grössere Sicherheitslücken entstehen könnten.
Für diese Anwendungen kann glücklicherweise auf einfachere Frameworks wie beispielsweise Slim 4 oder sehr umfangreiche wie Laravel zurückgegriffen werden, welche auch die notwendige Struktur und vor allem die aktuellen Sicherheitsstandards vorweisen können.
Mein komplettes GitHub-Repository mit dem Source-Code ist unter dem folgenden Link zu finden: https://github.com/sandroanderes/php-custom-api.
(spu)
Für mein Digezz-Projekt bin ich nach der IPERKA-Methode vorgegangen und möchte mit diesem auch die Kritik verfassen:
Informationen beschaffen
Da mich die Thematik der API weiterhin fasziniert und es in der IT vor allem auch in der Zukunft ein sehr grosser Bereich sein wird, wollte ich mich erneut damit auseinandersetzen. Das Node.JS-Framework des letzten Projektes ist zwar sehr fortschrittlich und zukunftsorientiert, allerdings vor allem in kleineren Projekten noch sehr selten anzutreffen. Da mir vor allem die Komplexität des Javascript-Frameworks sehr zugesetzt hatte, war es das Ziel, mit der bereits vertrauten Skriptsprache PHP eine Lösung zu finden. Um jedoch den kompletten Aufbau einer API genauer zu verstehen, habe ich mich dazu entscheiden, das Projekt ohne Framework umzusetzen und vollständig auf die eigene Realisierung zu setzen.
Ziel des Projektes:
- Einfach verständliche API welche jederzeit für kleinere Projekte verwendet werden kann.
Deadline:
- Publikationstermin Digezz (7. Januar)
Planen
Damit das Projekt reibungsfrei abläuft, mussten in der Planung einige Schritte beachtet werden. Als erstes musste ich mich erneut in die diversen Thematiken und Technologien einlesen und mir ein konkretes Produkt vorstellen. Als weiteren Schritt habe ich die einzelnen Teilaufgaben sowie die Meilensteine definiert. Als Letztes haben ich die einzelnen Tasks priorisiert und Reservezeit für Unerwartetes eingeplant.
Meilensteine:
– 1. August: Konkrete Projektidee definieren und Projektstart
– bis Ende September: Fertigstellung API
– bis Ende Dezember: Publikationsbericht und Kritik sowie letzte Änderungen
– 7. Januar: Publikationstermin
Entscheiden
Während der Planung war der grösste Entscheid die Wahl zwischen Framework und eigener Entwicklung, welcher, wie bereits im ersten Teil erwähnt, auf zweiteres Gefallen ist. Da es bei Digezz auch ums probieren und lernen geht, war dies für mich der logische und wohl auch richtige Schritt.
Realisieren
Da PHP bereits eine vertraute Materie war und ich auf einiges an Erfahrung zurückgreifen konnte, ist mir dieser Teil im Vergleich zu dem noch unbekannten Node.JS-Framework vom letzten Mal deutlich einfacher gefallen. Bei der Realisierung gab es trotzdem vor allem in den grundlegenden Zusammenhängen (Controller <-> Model) und der einigermassen ordentlichen Strukturierung einige Schwierigkeiten. Auch die korrekte Konfiguration über das .htaccess-File gestaltete sich schwieriger als vorerst gedacht. Vor allem, dass die «/» in der URL gelöscht und nicht in den Datenfluss einbezogen werden, bereitete mir einige Schwierigkeiten. Ein weiterer Punkt, welcher mir erst später im Projekt aufgefallen ist, waren einige Sicherheitslücken, welche mir vorerst nicht bewusst waren. Beispielsweise war es möglich, die Ordnerinhalte aufzulisten und so Einblick in die Struktur des Projektes zu erhalten, was jedoch relativ einfach zu beseitigen war.
Insgesamt gelang mir die Erstellung der API relativ speditiv und gut. Vor allem wurde mir bei diesem Projekt bewusst, wie genau die Abläufe und Datenübergabe detailliert funktionieren.
Kontrollieren
Damit bei der Abgabe keine Überraschungen auftreten, habe ich mich an folgende Vorgaben gehalten:
– Meilensteine überprüfen
– Vergleich von Planung und Umsetzung
– Eigen und Fremdkontrolle
– Qualitätskontrolle
Auswerten
Als letzten Teilschritt habe ich ein Fazit über das Gesamtprojekt gezogen und reflektiert, was ich in Zukunft besser machen kann.
Ich kann sagen, dass ich alle Ziele wie geplant erreicht habe und die Ressourcen, vor allem auch das Zeitmanagement optimal einsetzen konnte. Vor allem der vorzeitige Start bereits während den Semesterferien war sehr gut gewählt und hat mir während den Studientagen viel Zeit für weitere Projekte freigehalten. Für zukünftige Projekte würde ich weiterhin an der IPERKA-Methode festhalten und diese erneut so anwenden.
Was aber nicht zu vergessen ist, sind natürlich auch alle Learnings im Umgang mit der API und der korrekten Anwendung von PHP in einem solchen Umfeld. Dies waren wichtige Erfahrungen, welche ich auch zukünftig zu meinen Fertigkeiten dazuzählen darf.