Document ID: /fineweb-2-swissfilter-quality_10-filterrobots/filtered/03442.jsonl.gz/890

Du hast deine E-Commerce-, Digitalisierungs- und OPENAI-Experten gefunden.
Die in TYPO3 Flow verwendete Datenbankabstraktion namens Doctrine, erlaubt das Absetzen von Queries mittels der eigens entwickelten Sprache DQL. Hierbei werden im Unterschied zu herkömmlichen Query-Sprachen nicht die Datenbank und deren Tabellen, sondern die Objekte in der Applikation abgefragt. Es handelt sich also um eine Abstraktion der herkömmlichen Abfragesprachen.
In diesem Teil wird es vor allem PHP-Codes zu lesen geben, welche im Anschluss jeweils kurz erklärt werden. Dies bedeutet nicht, dass wir auf jede Kleinigkeit eingehen werden, da dies erstens einen ellenlangen Beitrag zur Folge hätte und zweitens davon ausgegangen wird, dass der Leser PHP- und TYPO3 Flow-Know-how mitbringt.
Der Einsatz von DQL in Flow ist einfach und schnell erklärt:
<?php /** @var \Doctrine\ORM\Query $query */ $query = $this->objectManager->get("Doctrine\Common\Persistence\ObjectManager")->createQuery("SELECT product FROM MyCompany\MyApplication\Domain\Model\Product product"); $this->results = new \Doctrine\Common\Collections\ArrayCollection($query->execute());
Es muss also zuerst ein DQL-Query-Objekt erstellt werden mit der entsprechenden Abfrage. Diese wird dann ausgeführt mit $query->execute, und in diesem Fall einer ArrayCollection hinzugefügt.
Weitere Informationen zu DQL-Syntax und -Funktionen finden Sie hier:
Entsprechendes Fachwissen wird hier aber nicht vorausgesetzt.
Ein DQL-Generator ist im Prinzip keine Anwendung, welche nur mit dynamischen Attributen Sinn macht, sondern kann genau so gut auch ohne diese funktionieren. Sie ist dann sogar um einiges einfacher zu programmieren. Im Zuge dieser Blog-Reihe gehen wir aber verständlicherweise von dynamischen Attributen aus. Ausserdem ist es nur beschränkt nötig, dynamische Reporte zu generieren, wenn die Klassenattribute selber nicht dynamisch sind.
Wir wollen also eine Seite, wo unsere Benutzer folgende Eingaben machen können:
Nun wird das Ganze ein bisschen komplizierter…
Der Name des Reports stellt kein Problem dar, diesen können wir wie gewohnt mit Flow auf dem Objekt speichern. Danach wird es bereits komplizierter: Woher wissen wir, welche Datenquellen verfügbar sind? Wir werden dazu die Reflection Services von Flow benutzen (aber noch ein bisschen erweitern).
Dasselbe gilt für die anderen Werte, welche wir benötigen. Zusätzlich gibt es aber noch Syntaxelemente, welche wir statisch einfügen müssen. Dabei handelt es sich um Elemente wie “ist grösser als” oder “ist gleich” und so weiter. Ausserdem kann es bei den Bedingungen Freitext-Werte geben, welche ebenfalls behandelt werden müssen.
Gleichermassen gibt es unzählige weitere Spezialfälle wie Datumsfelder, was aber aus Gründen der Übersicht ebenfalls nicht hier behandelt wird.
Wie also sollen wir all dies dem User anzeigen, ohne diesen gänzlich zu verwirren?
Die Idee ist, dass wir bei der Auswahl der Datenquelle nicht den für den Anwender unschönen Wert “\MyCompany\MyApplication\Domain\Model\Product”, sondern nur “Produkt” anzeigen. Dasselbe gilt natürlich für alle Attribute. Für Dynamische können wir die im letzten Teil besprochenen DataFields verwenden, da dort der Name des Attributs für die Ausgabe gespeichert ist. Für alle Anderen und für die Datenquellen benutzen wir ein Translation-File und die Übersetzungsfunktionalität von TYPO3 Flow.
Und auch weiterhin werden wir den Kunden natürlich unterstützen.
Ausserdem wollen wir, dass der Nutzer weiss, was er eingeben kann. So können wir mit Autovervollständigung (z.B. typeahead.js von Twitter) und Hilfefenstern (z.B. in Form von Modals) ihn dabei unterstützen. Nach der Eingabe werden die validierten Werte nicht als Freitext, sondern als so genannte Tags gespeichert (siehe z.B. https://github.com/bootstrap-tagsinput/bootstrap-tagsinput). So können Tippfehler oder versehentliches Löschen von einzelnen Buchstaben verhindert werden.
Trotzdem: Uns muss bewusst sein, dass ein gewisses Verständnis und Technikaffinität vorhanden sein muss, um diesen Generator zu bedienen.
Wir brauchen für den DQL-Generator zwei Klassen:
Die Trennung ist nicht zwingend erforderlich, da es sich hierbei um eine 1:1-Beziehung handelt. Trotzdem ist es der Übersicht halber sinnvoll.
CODE
https://gist.github.com/randm-ch/fa731a0a5d8fd3c422ff (Report.php)
Hier werden bei der Methode getResults() auch die Ergebnisse des Reports aus der Datenbank gelesen.
Da es möglich ist, dass gewisse Attributnamen bei mehreren Objekten vorkommen, wird bei der Abfrage jeweils eine Nummer angehängt. Diese wird bei der Anzeige mittels der Methode getPropertyNames() wieder entfernt.
CODE
https://gist.github.com/randm-ch/d95f35aa1f04d1ed745c (DqlStatement.php)
Die generate()-Methode ist hier der Zentrale Punkt. Sie erstellt die DQL-Statements aus den Formularwerten. Ausserdem werden in dieser Klasse die statischen Werte wie LEFT JOIN oder IS NULL definiert.
CODE
https://gist.github.com/randm-ch/66e7bcfada8d85608fcc (ReportController.php)
Im Controller müssen zweierlei Dinge erledigt werden:
Ausserdem gibt es hier zwei Helper-Methoden:
Dem neugierigen Leser ist im Controller-Code aufgefallen: Eine weitere Klasse wird dringend benötigt. Richtig, \MyCompany\MyApplication\Utility\DataClassReflection wird als Nächstes behandelt.
CODE
https://gist.github.com/randm-ch/adcacf8b9390aa563b38 (DataClassReflection.php)
In getForbiddenProperties() können Sie definieren, welche Attribute dem Benutzer nicht zur Auswahl stehen. Die drei im Code Implementierten sind mehr oder weniger Pflicht, ansonsten könnten Infinite-Loops erzeugt werden.
Ausserdem müssen wir, um den Code zum funktionieren zu bewegen, die TagsinputTag-Klasse entwickeln. Hierbei handelt es sich um einen Wrapper, welcher einen Tagsinput-Tag beschreibt:
CODE
https://gist.github.com/randm-ch/b535a380caa1a21d5d7e (TagsinputTag.php)
Ein Tag hat jeweils einen Typ, möglich sind folgende:
Der Typ definiert, in welchem Input-Feld der Tag eingesetzt werden kann und welche Farbe er hat. Mehr dazu weiter unten in der View-Beschreibung.
In der TagsinputTag-Klasse wird wiederum ein TagsinputTagInjector verwendet. Dieser wird benötigt, um die Übersetzungsfunktionalität von TYPO3 Flow zu verwenden, damit wir dem User nicht unsere Klassennamen und Attributnamen (normalerweise in Englisch) anzeigen müssen, sondern übersetzte Strings.
CODE
https://gist.github.com/randm-ch/297cef9159b49c59d2b1 (TagsinputTagInjector.php)
Diese Templates sind nötig, um den DQL-Generator laufen zu lassen. Ein TYPO3-Fluid-Layout, basierend auf Twitter Bootstrap, wird vorausgesetzt.
CODE Reporte anzeigen (Templates/Report/Index.html)
CODE Einen neuen Report generieren (Templates/Report/New.html)
CODE Einen Report bearbeiten (Templates/Report/Edit.html)
CODE Einen Report anzeigen (Templates/Report/Show.html)
CODE Hilfetext für Datenquelle (Templates/Report/FromQuery.html)
CODE Hilfetext für Verknüpfungen (Templates/Report/JoinQuery.html)
CODE Hilfetext für Felder (Templates/Report/SelectQuery.html)
CODE Hilfetext für Bedingungen (Templates/Report/WhereQuery.html)
jQuery wird vorausgesetzt, um die Tagsinput-Library verwenden zu können.
CODE
https://gist.github.com/randm-ch/55b2b069c07fc62d7caf (Scripts/tagsinput.js)
Dieses Script aktiviert die Autosuggest-Funktion, erstellt ein Tag – mit entsprechendem Typ, wie oben beschrieben – und fügt dieses in das entsprechende Input-Feld
Was haben wir erreicht?
Damit sind alle Arbeiten abgeschlossen und der Generator kann nun verwendet werden.