Ich entwerfe und implementiere derzeit eine RESTful-API in PHP. Es ist mir jedoch nicht gelungen, mein ursprüngliches Design zu implementieren.
GET /users # list of users
GET /user/1 # get user with id 1
POST /user # create new user
PUT /user/1 # modify user with id 1
DELETE /user/1 # delete user with id 1
Soweit ziemlich normal, oder?
Mein Problem ist mit dem ersten GET /users
. Ich habe überlegt, Parameter im Anforderungshauptteil zu senden, um die Liste zu filtern. Dies liegt daran, dass ich in der Lage sein möchte, komplexe Filter anzugeben, ohne eine super lange URL zu erhalten, wie zum Beispiel:
GET /users?parameter1=value1¶meter2=value2¶meter3=value3¶meter4=value4
Stattdessen wollte ich so etwas haben wie:
GET /users
# Request body:
{
"parameter1": "value1",
"parameter2": "value2",
"parameter3": "value3",
"parameter4": "value4"
}
Das ist viel besser lesbar und bietet Ihnen großartige Möglichkeiten, komplexe Filter einzustellen.
Der Anfragetext file_get_contents('php://input')
für GET
Anfragen wurde sowieso nicht zurückgegeben . Ich habe es auch versucht http_get_request_body()
, aber das von mir verwendete Shared Hosting hat es nichtpecl_http
. Ich bin mir nicht sicher, ob es trotzdem geholfen hätte.
Ich fand diese Frage und stellte fest, dass GET wahrscheinlich keinen Anfragetext haben soll. Es war ein bisschen nicht schlüssig, aber sie rieten davon ab.
Jetzt bin ich mir nicht sicher, was ich tun soll. Wie entwirft man eine RESTful-Such- / Filterfunktion?
Ich nehme an, ich könnte es gebrauchen POST
, aber das scheint nicht sehr ruhig zu sein.
Antworten:
Der beste Weg, eine RESTful-Suche zu implementieren, besteht darin, die Suche selbst als Ressource zu betrachten. Dann können Sie das POST-Verb verwenden, weil Sie eine Suche erstellen. Sie müssen nicht buchstäblich etwas in einer Datenbank erstellen, um einen POST zu verwenden.
Zum Beispiel:
Sie erstellen eine Suche vom Standpunkt des Benutzers aus. Die Implementierungsdetails hierfür sind irrelevant. Einige RESTful-APIs benötigen möglicherweise nicht einmal Persistenz. Das ist ein Implementierungsdetail.
quelle
Wenn Sie den Anforderungshauptteil in einer GET-Anforderung verwenden, verstoßen Sie gegen das REST-Prinzip, da Ihre GET-Anforderung nicht zwischengespeichert werden kann, da das Cache-System nur die URL verwendet.
Und was noch schlimmer ist, Ihre URL kann nicht mit einem Lesezeichen versehen werden, da die URL nicht alle Informationen enthält, die erforderlich sind, um den Benutzer auf diese Seite umzuleiten
Verwenden Sie URL- oder Abfrageparameter anstelle von Anforderungshauptteilparametern.
z.B:
In der Tat sagt der HTTP RFC 7231, dass:
Eine Nutzlast innerhalb einer GET-Anforderungsnachricht hat keine definierte Semantik. Das Senden eines Nutzdatenkörpers für eine GET-Anforderung kann dazu führen, dass einige vorhandene Implementierungen die Anforderung ablehnen.
Weitere Informationen finden Sie hier
quelle
Es scheint, dass das Filtern / Suchen von Ressourcen auf REST-fähige Weise implementiert werden kann. Die Idee ist, einen neuen Endpunkt namens
/filters/
oder einzuführen/api/filters/
.Mit diesem Endpunkt Filter kann als Ressource betrachtet werden und somit über erstellt
POST
Methode. Auf diese Weise kann - body - natürlich verwendet werden, um alle Parameter zu übertragen, und es können komplexe Such- / Filterstrukturen erstellt werden.Nach dem Erstellen eines solchen Filters gibt es zwei Möglichkeiten, um das Such- / Filterergebnis zu erhalten.
Eine neue Ressource mit eindeutiger ID wird zusammen mit zurückgegeben
201 Created
Statuscode zurückgegeben. Unter Verwendung dieser IDGET
kann dann eine Anfrage gestellt werden, um Folgendes zu/api/users/
mögen:Nachdem ein neuer Filter über erstellt wurde
POST
antwortet er nicht mit,201 Created
sondern sofort mit303 SeeOther
zusammen mit demLocation
Header, der auf zeigt/api/users/?filterId=1234-abcd
. Diese Umleitung wird automatisch über die zugrunde liegende Bibliothek abgewickelt.In beiden Szenarien müssen zwei Anforderungen gestellt werden, um die gefilterten Ergebnisse zu erhalten. Dies kann insbesondere für mobile Anwendungen als Nachteil angesehen werden. Für mobile Anwendungen würde ich Single
POST
Call to verwenden/api/users/filter/
.Wie werden erstellte Filter beibehalten?
Sie können in der Datenbank gespeichert und später verwendet werden. Sie können auch in einem temporären Speicher gespeichert werden, z. B. redis, und haben eine TTL, nach der sie ablaufen und entfernt werden.
Was sind die Vorteile dieser Idee?
Filter und gefilterte Ergebnisse können zwischengespeichert werden und können sogar mit Lesezeichen versehen werden.
quelle
Ich denke, Sie sollten mit Anforderungsparametern arbeiten, aber nur solange es keinen geeigneten HTTP-Header gibt, um das zu erreichen, was Sie tun möchten. Die HTTP-Spezifikation besagt nicht explizit, dass GET keinen Body haben kann. In diesem Papier heißt es jedoch:
quelle
Da ich ein Laravel / PHP- Backend verwende, tendiere ich dazu, Folgendes zu wählen :
PHP
[]
wandelt Parameter automatisch in ein Array um. In diesem Beispiel erhalte ich eine$filter
Variable, die ein Array / Objekt von Filtern sowie eine Seite und alle zugehörigen Ressourcen enthält, die ich unbedingt laden möchte.Wenn Sie eine andere Sprache verwenden, ist dies möglicherweise immer noch eine gute Konvention, und Sie können einen Parser erstellen, der
[]
in ein Array konvertiert wird .quelle
[
und vermieden werden]
. Die Verwendung codierter Darstellungen dieser Zeichen zum Gruppieren von Abfrageparametern ist eine bekannte Praxis. Es wird sogar in der JSON: API-Spezifikation verwendet .Ärgern Sie sich nicht zu sehr, wenn Ihre anfängliche API vollständig REST-fähig ist oder nicht (insbesondere, wenn Sie sich gerade in der Alpha-Phase befinden). Lassen Sie die Back-End-Installation zuerst funktionieren. Sie können jederzeit eine Art URL-Transformation / Umschreiben durchführen, um die Dinge abzubilden, und iterativ verfeinern, bis Sie etwas erhalten, das für umfassende Tests stabil genug ist ("Beta").
Sie können URIs definieren, deren Parameter durch Position und Konvention auf den URIs selbst codiert werden, wobei ein Pfad vorangestellt wird, von dem Sie wissen, dass Sie ihn immer etwas zuordnen werden. Ich kenne PHP nicht, aber ich würde annehmen, dass eine solche Funktion existiert (wie sie in anderen Sprachen mit Web-Frameworks existiert):
.ie. Führen Sie eine "Benutzer" -Suche mit param [i] = value [i] für i = 1..4 in Geschäft Nr. 1 durch (mit value1, value2, value3, ... als Abkürzung für URI-Abfrageparameter):
oder
oder wie folgt (obwohl ich es nicht empfehlen würde, dazu später mehr)
Mit Option 1
/store1/search/user
ordnen Sie alle URIs dem Suchhandler (oder der PHP-Bezeichnung) zu, die standardmäßig nach Ressourcen unter store1 suchen (entspricht)/search?location=store1&type=user
.Gemäß der von der API dokumentierten und erzwungenen Konvention werden die Parameterwerte 1 bis 4 durch Kommas getrennt und in dieser Reihenfolge dargestellt.
Option 2 fügt den Suchtyp (in diesem Fall
user
) als Positionsparameter 1 hinzu. Jede Option ist nur eine kosmetische Wahl.Option 3 ist ebenfalls möglich, aber ich glaube nicht, dass es mir gefallen würde. Ich denke, die Fähigkeit der Suche innerhalb bestimmter Ressourcen sollte in der URI selbst vor der Suche selbst dargestellt werden (als ob in der URI klar angegeben würde, dass die Suche innerhalb der Ressource spezifisch ist.)
Dies hat gegenüber der Übergabe von Parametern an den URI den Vorteil, dass die Suche Teil des URI ist (wodurch eine Suche als Ressource behandelt wird, eine Ressource, deren Inhalt sich im Laufe der Zeit ändern kann und wird). Der Nachteil besteht darin, dass die Parameterreihenfolge obligatorisch ist .
Sobald Sie so etwas tun, können Sie GET verwenden, und es wäre eine schreibgeschützte Ressource (da Sie nicht POSTEN oder PUTEN können - es wird aktualisiert, wenn es GET'ed ist). Es wäre auch eine Ressource, die nur dann existiert, wenn sie aufgerufen wird.
Sie können auch mehr Semantik hinzufügen, indem Sie die Ergebnisse für einen bestimmten Zeitraum zwischenspeichern oder mit einem LÖSCHEN den Cache löschen. Dies kann jedoch dem widersprechen, wofür Benutzer normalerweise DELETE verwenden (und weil Benutzer das Caching normalerweise mit Caching-Headern steuern).
Wie Sie vorgehen, wäre eine Designentscheidung, aber so würde ich vorgehen. Es ist nicht perfekt, und ich bin sicher, dass es Fälle geben wird, in denen dies nicht das Beste ist (insbesondere für sehr komplexe Suchkriterien).
quelle
Zu Ihrer Information: Ich weiß, dass dies etwas spät ist, aber für alle, die interessiert sind. Abhängig davon, wie RESTful Sie sein möchten, müssen Sie Ihre eigenen Filterstrategien implementieren, da die HTTP-Spezifikation diesbezüglich nicht sehr klar ist. Ich möchte vorschlagen, alle Filterparameter mit einer URL zu codieren, z
Ich weiß, dass es hässlich ist, aber ich denke, es ist der RESTVOLLSTE Weg, es zu tun und sollte auf der Serverseite leicht zu analysieren sein :)
quelle