Experimental: List patch + sorting #2196
Closed
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What we want to achieve
Um Elemente umzusortieren wollen wir mehrere Elemente einer Liste gleichzeitig patchen, um das position property zu aktualisieren.
Im alten Backend hatten wir das gelöst, in dem wir PATCH auf collections erlaubt hatten, bzw. selbst implementiert haben. Siehe z.B. den PR #689 oder die patchList function im Abstract Entity Service. Der request payload sah dabei so aus:
List patch in API Platform
Patchen von collections ist in API Platform aktuell nicht implementiert oder vorgesehen.
Mögliche Varianten:
Variante 1 (in diesem Pull request als Draft drin)
Updaten von mehreren Entities via embedded relation: Mittels
writableLink: true
können mittels POST/PATCH/PUT auf die Owning/Parent-side einer Relation auch Subelemente der Relation erstellt oder aktualisiert werden.https://api-platform.com/docs/core/operations/
Wir erlauben das heute schon z.B. beim Erstellen von Camps: Perioden können beim Erstellen auch gleich mitgeliefert werden und werden mit-erzeugt.
Laut Doku kann ein
@id
(oderid
?) property mitgeliefert werden, dann wird die die entsprechende Entity aktualisiert. Ansonsten wird eine neue erstellt:Hab ich out-of the Box nicht zum Laufen gebracht. Früher war das anscheinend nur für PUT möglich (wobei API Platform's PUT eigentlich wie ein PATCH funktioniert). Inzwischen ist PATCH auch in der Docu, funktioniert aber dennoch nicht.
Bin noch nicht sicher ob dies ein Bug ist oder ob das davon kommt, dass API Platform versucht, die JSON Merge Patch Spezifikation strikt zu befolgen. Wird auf API Platform auch in mehreren Issues diskutiert. Geholfen hat mir dieser Workaround:
api-platform/core#4293 (comment)
Der ist nun im PR auch implementiert. Ist super hacky und setzt stark voraus, dass man die Interna von API Platform kennt (=Chance gross, dass das dann mit einem Upgrade von API Platform kaputt geht). Aber es funktioniert.
Vorteil: Theoretisch ist der Use-case von API Platform unterstützt (evt. Verbesserungen in zukünftigen Versionen)
Nachteil: Die Subentities werden nicht nur aktualisiert, sondern je nach dem auch erstellt oder entfernt (!). Dieses Verhalten ist bei einem reinen Resorting nicht wirklich gewünscht.
Variante 2: List patch als custom operation
List patch (oder spezifisch nur list sort?) als eigene custom operation implementieren
Variante 3: JSON Patch
Warten, bis JSON Patch format implementiert ist: api-platform/core#759
Variante 4: Nur jeweils eine Entity aktualisieren
Implementieren des Sortierens ohne auf list patch angewiesen zu sein. Das wäre theoretisch in Verbindung mit der doctrine-extension sortable möglich. Allerdings muss dann Frontend-seitig und Backend-seitig die Logik gleichermassen implementiert sein, sonst führt dies zu Inkonsistenzen.
Oder: man setzt ein PATCH auf die verschobene Entity ab und lädt danach die komplette Liste neu.
doctrine extension sortable
Docu hier:
https://github.com/doctrine-extensions/DoctrineExtensions/blob/main/doc/sortable.md
Vorteile/Features:
Nachteile:
UpdateStorybordTest
im gleichen Aufruf Sections aktualisiert und neue hinzugefügt. Und das hat schon mal inkonsistente Daten produziert.Alternative 1: Keine Logik Backendseitig einbauen und die Verantwortung an das Frontendend geben, vernünftige Daten in das position Property zu schreiben.
Alternative 2: Kein Bulk-Update erlauben, sondern nur einzelne Entitäten. Dann muss Frontendseitig die Berechnung der Position aber konsistent sein mit der Backend-Logik. Oder ich muss die Collection neu laden, damit ich die neuen position properties aller Entities habe.
Im alten Backend hatten wir lediglich eine Logik drin, welche eine neue Entität ans Ende stellte, wenn das position property beim Erstellen nicht gesetzt wurde:
https://github.com/ecamp/ecamp3/blob/devel/backend/module/eCampCore/src/EntityService/ContentNodeService.php#L109