dbxReport ist die Listenpipeline von dbxapp. Sobald eine Ansicht Suche, Sortierung, Pagination, Zeilenaktionen oder Mehrfachauswahl benötigt, sollte sie nicht als eigene Schleife mit eigener UI-Logik entstehen.
Einordnung im Golden Path
Verbindliches Modulhandbuch zeigt einen vollständigen Report mit Selection-FD, sicherer Sortierung, Zeilenaktionen, Confirm und Ajax. Dieses Kapitel vertieft Table-, TPL-, Grid-, Auswahl- und Callback-Fähigkeiten.
dbxReport erweitert bewusst dbxForm: Reportfilter sind Formfelder und verwenden denselben validierten Zustand. Die gemeinsame Pipeline ist ein Kompatibilitätsvorteil, kein Anlass für zwei konkurrierende Formularsysteme. Das gilt auch für sprachabhängige Selection-FDs und deren $messages: dbxReport verwendet dieselbe Dateiauflösung, denselben Cache sowie save_success und save_error im geerbten Speicherpfad. Eine zweite Report-spezifische Meldungslogik ist nicht erforderlich.
Für Reporttitel, Spaltenköpfe, Statuswerte, Bestätigungen und Footer gilt derselbe Vertrag. load_fd_messages() lädt eine Selection-FD auch dann, wenn der Report keine sichtbaren Filterfelder benötigt; format_fd_message() ersetzt dynamische Platzhalter:
Auch bei einem Report ohne sichtbare Selection-Felder wird _fd vor Spaltenaufbau und Meldungszuweisung gesetzt. Titel, Spaltenköpfe, Statuslabels, leere Zustände, Summenbeschriftungen und fachliche Confirmtexte stammen aus diesem FD-Vertrag:
dbxReport benötigt dafür keinen zweiten Übersetzungsmechanismus, weil es die komplette FD- und Meldungspipeline von dbxForm erbt. Datenwerte aus einer einsprachigen Tabelle werden davon bewusst nicht übersetzt.
Fähigkeiten
- Tabellen-, Template- und Grid-Ausgabe.
- DD-/FD-basierte Filterfelder.
- Suche, Sortierung, Seitenlänge und Offset.
- Einzelaktionen wie Anzeigen, Bearbeiten, Kopieren oder Löschen.
- seitenübergreifende Auswahl und Multi-Aktionen.
- Ausgabeformate und bewusst freigegebene HTML-Spalten.
- Callbacks für Report-, Seiten-, Tabellen- und Datensatzebene.
- AJAX-Reload in ein eindeutiges Report-Target.
Lebenszyklus
Reales Tabellenreport-Muster
Das folgende Beispiel entspricht dem Workflow-Adminreport und verwendet bewusst getrennte Gesamtzahl, Trefferzahl und Datensätze:
Warum die Werte getrennt werden
| Eigenschaft | Bedeutung |
|---|---|
| _count_all | alle grundsätzlich verfügbaren Datensätze |
| _rcount | Trefferzahl nach dem aktuellen Filter |
| _rrows | Zeilen pro Seite |
| _rpos | Offset der aktuellen Seite |
| _rdata | tatsächlich geladene Datensätze dieser Seite |
| _rflds | auszugebende Felder und Labels |
| _rpt_format | Format je Ausgabefeld |
Pagination funktioniert nur korrekt, wenn Zählung und Datenabfrage dieselbe WHERE-Bedingung verwenden.
Selection-FD für Filter und Sortierung
Sortierfelder werden als feste Optionsliste vorgegeben und im Controller zusätzlich gegen dieselbe Allowlist geprüft. Das ist wichtig, weil ein Request manipuliert werden kann und ORDER BY keine freie Benutzereingabe erhalten darf.
Report-Template mit dbx_split
dbx_split teilt ein Reporttemplate in Header, wiederholte Zeile und Footer. [rpt:row] wird im Header durch Spaltenköpfe und im Body durch Zellen ersetzt. Das reale Template steht unter dbx/modules/dbxWorkflow_admin/tpl/htm/workflow-definitions.htm.
Ausgabeformate und HTML
Reportwerte laufen durch die Reportformatierung. Normale DD-Werte werden nicht im Modul pauschal escaped. Konvertierungen und bewusst erzeugte Komponentenfragmente werden feldweise angegeben:
html ist nur für serverseitig kontrollierte Fragmente geeignet. Ein zusätzliches html-chars ist nur dann sinnvoll, wenn ein roher Fremdwert ausdrücklich als literaler HTML-Text erscheinen soll. Es ist nicht der Standardwrapper für jeden Datenbankwert.
Zeilenaktionen
Eigene Aktionsspalte
Automatische Aktionen
dbxReport kann Standardaktionen erzeugen:
Der Controller muss die resultierenden dbx_do-Aktionen behandeln und danach wieder denselben Report rendern. UI-Erzeugung ersetzt keine Berechtigungsprüfung im Servercode.
Die mutierenden Standardaktionen row_delete, delete_tab, multi_delete sowie Aktivieren/Deaktivieren werden vom Report automatisch über dbxApi::action_url() signiert. dbxWebApp prüft die zugehörige Policy vor dem Modulstart. Filter, Report-Sortierung, Pagination, Show und Edit bleiben unverändert und tokenlos. Fachmodule bauen für diese Standardfälle weder eigene Scopes noch eigene Tokenprüfungen.
Auch individuelle Standard-Links brauchen keine Modulkonfiguration: delete oder save in dbx_run1, dbx_run2, dbx_run3 beziehungsweise dbx_do werden zusammen mit rid von dbx()->action_url($url) automatisch erkannt. dbxWebApp bindet die RID an den Scope und prüft den Request vor dem Modulstart. Modul- und DD-Rechte bleiben zusätzlich verbindlich.
Einzel- und Multi-Delete
Konfiguration für eine seitenübergreifende Auswahl:
Auswahlzustand wird über die Report-/Remember-Pipeline geführt. Keine parallele Session-Liste im Fachmodul anlegen.
Callbacks richtig einsetzen
dbxReport nutzt die von dbxForm geerbten Callback-Defaults. init() merkt sich den direkten Modul-/Service-Aufrufer als Owner. Die normalisierte Formular-ID ist der Methodenpräfix:
task-report sucht damit automatisch task_report_next_record(), task_report_body(), task_report_footer() und die weiteren Events. set_callback_owner() und set_*_callback() sind nur nötig, wenn bewusst ein anderer Owner oder Methodenname verwendet wird.
Explizite Abweichung:
Weitere Ebenen sind Report-Header, Page-Header, Tabellen-Header, Tabellen-Footer, Page-Footer und Report-Footer. Sie verändern bereits gerenderten Content. Für die Aufbereitung einzelner Zeilen ist der {fid}_next_record-Default die passendere Stelle.
Berechnete Summenspalte und Endsumme im Table-Footer
Eine virtuelle Spalte gehört nicht in eine zweite Datenbankschleife. Im table-Modus setzt der automatische Datensatz-Callback den Wert unmittelbar vor der Zeilenausgabe und aktualisiert den Footerwert spät per add_rep():
Die Report-ID aktiviert den Callback bereits über die Namenskonvention:
Der Bereich nach dem zweiten dbx_split ist der Tabellen-Footer und wird erst nach allen angezeigten Datensätzen verarbeitet:
Die von dbxForm geerbte replaces()-Pipeline wendet das zuletzt per add_rep() gesetzte Ergebnis beim Footerlauf an. {rpt:colspan} spannt automatisch über alle Spalten außer der letzten Summenspalte; {rpt:col_count} bleibt für die vollständige Spaltenzahl verfügbar. Im Rechnungsbeispiel ist der Positionsreport nicht paginiert, daher umfasst die Endsumme alle Positionen. Bei Pagination wäre es bewusst die aktuelle Seite.
Die drei Ausgabemodi
Table
Standard für Adminlisten, Bestellungen, Benutzer und Workflow-Instanzen. Er passt zu Sortierung, Pagination, Aktionen und responsiver Tabellenhülle.
TPL
Jeder Datensatz wird über ein Row-Template ausgegeben. Das eignet sich für Produktkarten, Dashboards, Medienkacheln und Activity-Feeds. Suche und Pagination bleiben trotzdem Teil von dbxReport.
Tabulator/Grid
Die Schreibweise tabulurator ist derzeit der intern verwendete Kompatibilitätswert. Der Modus ist für interaktive Datengitter und größere Admin-Datenmengen gedacht. Vor einer neuen Grid-Ansicht ein bestehendes Beispiel wie dbxSchema oder dbxContent_sections übernehmen, weil Spalten- und JavaScript-Konfiguration dazugehören.
Schreibende Grid-URLs müssen der vorhandenen dbxReport-Konvention folgen:
Die historischen dbxSchema-Varianten data_<aktion> und fields_<aktion> bleiben kompatibel. dbxReport signiert Save, Insert, Delete, Sort und Sync automatisch; Read bleibt tokenlos. dbxWebApp erkennt die eigentliche Zielroute auch bei einer direkt konstruierten Anfrage. Modulcode ergänzt keinen Marker und prüft keinen zweiten Token. Eine unbekannte schreibende Grid-Konvention wird fail-closed nicht als URL ausgegeben.
AJAX-Verhalten
Der Report besitzt ein eigenes Target:
Filter, Pagination und Aktionen sollen nach dem Request genau dieses Target neu rendern. Für mehrfach eingebettete Reports ist {i} zwingend; eine feste globale ID führt zu falschen Ersetzungen.
Verbindliche Regeln
- Listen mit Filter, Sortierung oder Pagination verwenden dbxReport.
- Auswahl- und Pagingzustand nicht neben der Reportpipeline duplizieren.
- Filterwerte validieren und WHEREs über dbxDB strukturiert bauen.
- _count_all, _rcount und _rdata konsistent berechnen.
- HTML nur für kontrollierte Spalten mit _rpt_format = 'html' freigeben.
- Zeilenaktionen im Template oder über Standardaktionen erzeugen, serverseitig aber immer erneut Rechte und Datensatz prüfen.
- Nach einer Aktion denselben Report für dasselbe Target rendern.
- Table, TPL und Grid nach Darstellungsziel wählen, nicht eigene Pipelines erfinden.
- Standardmutationen automatisch signieren lassen; individuelle mutierende Links deklarieren und über action_url() führen.
- {fid}_{event}-Callback-Defaults verwenden und Footerwerte spät per add_rep() setzen; reine str_replace()-Footer-Callbacks vermeiden.
Reale Referenzen
- dbx/modules/dbxWorkflow_admin/include/dbxWorkflowAdmin.class.php: filterbarer Tabellenreport und Workflow-Instanzen.
- dbx/modules/dbxAdmin/include/dbxWizard.class.php: vollständiges generiertes Muster mit Multi-Select, Multi-Delete und Callbacks.
- dbx/modules/dbxShop/include/dbxShopService.class.php: TPL-Report für Produktkarten.
- dbx/modules/dbxShop_admin/include/dbxShopAdmin.class.php: umfangreiche Tabellenreports und Massenaktionen.
- dbx/modules/dbxContent_admin/include/dbxContent_sections.class.php: Table-, TPL- und Grid-Varianten.
- Verbindliches Modulhandbuch — verbindliches Gesamtbeispiel.
- JavaScript-Systemlibs — Browserablauf für Report, Confirm und Ajax.