Hallo Habr!
Ich saß einmal und versuchte, dem Front-JSON Immobilien zu geben, die viele Abhängigkeiten hatten. Symfony 4, knp-Paginierung und JMSSerializer standen auf der Rückseite, im Prinzip Standard, aber das Problem ist, dass beim Versuch, einem Objekt alle verschachtelten Entitäten und Sammlungen zuzuweisen, alles auf der Serialisierungsebene dieser Daten langsamer wird.
Zuerst müssen Sie eine Anfrage an die Datenbank stellen, dann ruft der Serializer nach und nach alles andere auf, dann wird alles in JSON verpackt und erst dann kehrt alles nach vorne zurück.
Idee
Ich hatte eine Idee, warum nicht JSON direkt von der Datenbank direkt von hinten nach vorne zurückgeben, ja, Sie müssen fantastisches SQL schreiben, aber Sie können ein Tool erstellen, das dies für Sie erledigt. Ich habe mich daran gemacht, eine Idee zu schreiben, ein Repository auf einem Github , basierend auf dem Datenmodell aus der Lehre, OneToOne, ManyToOne, OneToMany und ManyToMany. Dieses Tool kann auch problemlos mit Symfony 4 verschraubt werden und konfiguriert sich selbst. Daher müssen Sie nur die QueryBuilderFactory-Factory injizieren und von dort aus QueryBuilder für die gewünschte Tabelle nach Entitätsklasse abrufen.
Mein Serializer verwendet auch Serialisierungsgruppen, die Sie mithilfe der Annotation Expose im Entitätsfeld festlegen können. Vergessen Sie nicht, die Tabellenanmerkung an die Entität anzuhängen und den Tabellenalias anzugeben. Verwenden Sie besser die normalerweise angegebenen.
Beispiel für die SQL-Generierung
<?php use \Mash\MysqlJsonSerializer\QueryBuilder\Table\JoinStrategy\FieldStrategy; use \Mash\MysqlJsonSerializer\Wrapper\FieldWrapper; use \Mash\MysqlJsonSerializer\QueryBuilder\Table\Table; use \Mash\MysqlJsonSerializer\Wrapper\Mapping; use \Mash\MysqlJsonSerializer\QueryBuilder\QueryBuilder; $oneToManyTable = (new Table('advert_group', 'adg', 'adg_id')) ->addSimpleField('adg_id') ->addSimpleField('adg_name') ; $table = (new Table('estate', 'est', 'est_id')) ->addSimpleField('est_id') ->addSimpleField('est_name') ->addOneToManyField($oneToManyTable, 'advert_groups', new FieldStrategy('adg_estate')); $mapping = new Mapping(); $mapping ->addMap($table, 'est_id', 'id') ->addMap($table, 'est_name', 'name') ->addMap($oneToManyTable, 'adg_id', 'id') ->addMap($oneToManyTable, 'adg_name', 'name'); $builder = new QueryBuilder($table, new FieldWrapper($mapping)); $builder ->setOffset(2) ->setLimit(1); $sql = $builder->jsonArray();
Als Ergebnis wird das folgende SQL generiert:
SELECT JSON_ARRAYAGG(JSON_OBJECT('id',est_res.est_id,'name',est_res.est_name,'advert_groups',(SELECT JSON_ARRAYAGG(JSON_OBJECT('id',adg.adg_id,'name',adg.adg_name)) FROM advert_group adg INNER JOIN estate est_2 ON est_2.est_id = adg.adg_estate WHERE est_2.est_id = est_res.est_id))) FROM (SELECT * FROM estate est LIMIT 1 OFFSET 2) est_res
Ergebnis:
[{"id": 3, "name": ", , 31", "advert_groups": [{"id": 10, "name": "avito-1115362430"}]}]
Zusammenfassung
Vollständige Gebrauchsanweisungen werden demnächst zum Github-Repository hinzugefügt. Als ich es in mein Projekt schraubte, erhielt ich sehr schnelle Antworten von der REST-API und gleichzeitig konnte ich viele Objekte mit vielen verschachtelten Abhängigkeiten zurückgeben, zum Beispiel, was ich jetzt für 40 Sekunden über JMSSerializer erhalten wollte 230 Millisekunden, und dies vorausgesetzt, dass der Kernel-Abonnent Anmerkungen zu Entitätsfeldern durch Reflektion liest, möchte ich dies bald durch Cache-Symfony implementieren.
Der Artikel wird ergänzt ...
Zweiter Teil