dbxapp Wissen dbxapp Modulhandbuch – Grundlagen und Sicherheitsvertrag

dbxapp Modulhandbuch – Grundlagen und Sicherheitsvertrag

Modulhandbuch · Kapitel 1 von 8

Grundlagen und Sicherheitsvertrag

Zielbild, Schichtentrennung, Kernelgrenzen, Verzeichnisstruktur sowie Routing- und Sicherheitsvertrag.

Referenzstand: 25. Juli 2026
Beispielmodul: myInvoices

Dieses Kapitel ist der verbindliche Golden Path für ein datenbasiertes dbxapp-Modul. Das vollständige Beispiel verwaltet Rechnungen und deren Artikelpositionen. Es verbindet dbxTPL, dbxDB, DD, FD, dbxForm, dbxReport, Modul-Inclusion, ajax.js und confirm.js in einem zusammenhängenden Ablauf.

Das Beispiel ist nicht nur Pseudocode. Die installierbare Referenz liegt unter dbx/modules/myInvoices/. Die Codeblöcke dieses Kapitels erklären die entscheidenden Verträge; die Moduldateien, Fixtures und ausführbaren Tests sind die maßgebliche, gemeinsam gepflegte Fassung.

Die Wörter MUSS, DARF NICHT, SOLL und DARF sind normativ:

  • MUSS und DARF NICHT beschreiben den dbxapp-Vertrag.
  • SOLL ist die Standardentscheidung; eine Abweichung braucht einen dokumentierten fachlichen Grund.
  • DARF bezeichnet eine unterstützte Variante.

Das Zielbild

Die erste Listenstufe zeigt Rechnungen. Direkt unter jeder Rechnungszeile ruft ein serverseitiger Modulmarker die zweite Listenstufe auf:

[modul=myInvoices]dbx_run1=positions&invoice_id=17[/modul]

Die zweite Stufe zeigt die Artikelpositionen genau dieser Rechnung. Ihr Record-Callback berechnet für jede Position Menge * Einzelpreis, setzt die virtuelle Spalte sum und sammelt Centbeträge. Ihr Footer-Callback setzt die Endsumme und berechnet den benötigten colspan aus der tatsächlich von dbxReport aufgebauten Spaltenzahl.

Request oder [modul=myInvoices]
|
v
kleiner Router myInvoices.class.php
|
v
myInvoicesService
| | |
| | +--> dbxTPL --> HTML-Templates
| +--------------> dbxForm / dbxReport --> FD
+-------------------------> dbxDB --> DD --> SQLite/MySQL
|
Rechnungsreport v
+--> [modul=myInvoices] --> Positionsreport je Rechnung
Browser:
core.js --> confirm.js --> ajax.js --> gleicher Modulrequest

Der [modul=...]-Aufruf ist kein zweiter Browserrequest. Der dbxInterpreter setzt die angegebenen Parameter als geschützte Modulvariablen, ruft den Modulrouter im aktuellen Owner-Kontext auf und ersetzt den Marker serverseitig durch das Ergebnis. Modulzugriff und DD-Rechte bleiben aktiv.

confirm.js entscheidet nur, ob eine Benutzeraktion fortgesetzt wird. ajax.js transportiert den Request und ersetzt HTML. Berechtigung, Validierung, Transaktion und Mutation bleiben vollständig auf dem Server.

Welche Schicht entscheidet was?

Frage Zuständige Schicht Nicht dort ablegen
Welche Route läuft? Modulrouter SQL, Formularaufbau, Markup
Welche fachliche Operation läuft? Service Layoutdetails
Woher kommen Daten? dbxDB über DD PDO oder SQL im Modul
Wie sehen Tabellen und Rechte aus? DD Controller-Arrays
Welche Felder zeigt ein Formular? FD zweite Tabellenbeschreibung
Wie wird eingegeben und validiert? dbxForm direkte $_POST-Speicherung
Wie werden beide Stufen gelistet? je ein dbxReport eigene Tabellenloops
Wie wird eine Unterliste eingebettet? [modul=...]...[/modul] interner HTTP-Aufruf
Wie wird HTML strukturiert? dbxTPL-Template große PHP-HTML-Strings
Wie werden Zeilenwerte berechnet? Record-Callback Zusatzschleife nach dem Report
Wie wird die Endsumme gesetzt? Footer-Callback JavaScript-Nachberechnung
Wer darf mutieren? Modulzugriff, DD-Rechte, ggf. Action-Token Confirm-Dialog

Warum die großen Kernelklassen nicht nach Größe geteilt werden

dbxDB, dbxDD, dbxForm und dbxReport sind stabile Systemfassaden und Pipelines. Ihre Größe folgt ihrer Fähigkeitstiefe:

  • dbxDB vereinheitlicht Server, DD-Auflösung, Rechte, Owner-Filter, Transaktionen, Trace, Fehler und Performance.
  • dbxDD erweitert den Datenpfad um Schema-, Backup-, Restore- und Transferprozesse.
  • dbxForm hält einen vollständigen Formularzustand von FD/DD bis Validierung, Meldung, Submit-Schutz und Rendern.
  • dbxReport erweitert dbxForm um Selection-Felder, Pagination, Zeilenaktionen, Auswahlzustand, Callbacks und mehrere Ausgabemodi.

Eine Kernelaufteilung ist nur mit stabiler Fassade, Regressionstests und einer bewiesenen Verantwortungsgrenze sinnvoll. Fachmodule dürfen dagegen echte Fachlogik in Services oder Repositories gliedern. Sie dürfen Kernel-Funktionen nicht durch eigene Methoden nachbauen, die nur dbx() weiterreichen.

Verzeichnisstruktur des Referenzmoduls

dbx/modules/myInvoices/
myInvoices.class.php
cfg/config.php
include/myInvoicesService.class.php
include/myInvoicesFixtures.class.php
dd/invoice.dd.php
dd/invoiceItem.dd.php
fd/invoice-form.fd.php
fd/rpt-invoice-selection.fd.php
tpl/htm/invoice-form.htm
tpl/htm/invoice-report.htm
tpl/htm/invoice-items-report.htm
tpl/htm/invoice-row-action.htm
tpl/htm/invoice-install.htm
tpl/htm/install-required.htm
tools/install_demo.php
tests/myInvoices_contract_test.php
tests/myInvoices_integration_test.php
tests/README.md
README.md

Die zwei Tabellen liegen auf demselben DD-Server. Dadurch kann eine Mehrtabellenmutation über eine gemeinsame dbxDB-Transaktion laufen.

Routen- und Sicherheitsvertrag

Route Zweck Zustand ändert sich? Schutz
dbx_run1=report Rechnungen, Filter, Pagination nein Modul- und DD-Leserecht
dbx_run1=positions&invoice_id=17 eingebettete Positionen nein Modul- und beide DD-Leserechte
dbx_run1=form&rid=17 Rechnungskopf bearbeiten POST ja dbxForm plus DD-Schreibrecht
dbx_run1=delete&rid=17 Rechnung samt Positionen löschen ja Modulrecht, DD-Löschrecht, Action-Token
dbx_run1=install DD-Sync und idempotente Demo-Fixtures POST ja Adminrecht und dbxForm

Normale Navigation, Filter, Report und Positions-Inclusion bleiben tokenlos. Ein Standardformular erhält keinen zusätzlichen dbx_token, weil dbxForm seinen Submit schützt. Bei der schreibenden Delete-URL erkennt dbxApi::action_url() die Kombination aus delete und rid automatisch, bindet die RID und ergänzt den Token. dbxWebApp prüft ihn vor dem Aufruf des Moduls. Eine action_routes-Konfiguration ist dafür nicht nötig.

DD- und Modulrechte beantworten, wer handeln darf. Der Action-Token beweist zusätzlich, dass der mutierende GET aus dem aktuellen Browserkontext stammt. Er ersetzt keine Rechteprüfung.