Framwork Vorschlag - Feedback erwünscht

  • Ich habe schon öfters mal was wegen dem Framework gelesen und ehrlich gesagt ist es ab und an auch echt nervig Sachen anzupassen ohne das ganze ui Zerstören.

    Also habe ich mal ein paar Stunden Investiert und ein kleines rework angefangen.
    Dies ist jetzt an einem Punkt angekommen wo es anfängt wirklich in Arbeit auszuarbeiten um entsprechende Details und Worksflows umzusetzten.
    Entsprechend hätte ich gerne eure Meinungen und Feedback dazu, macht es Sinn hier weiter zu machen oder ist es am ende vergebe Lebensmühe weil es sehr stark von Original Techstack abweicht und von Eurer Seite da kein Interesse besteht es so zu machen.

    Basics:


    Backend (Core)

    Runtime: Node.js 20 LTS

    Framework: NestJS (Enterprise TypeScript Framework)

    Sprache: TypeScript 5.x

    ORM: Prisma (State-of-the-art für Typsicherheit und DX)

    Validierung: Zod (Schema-basierte Validierung für API und DB)

    Frontend (Core)

    Framework: Next.js 14/15+ (App Router Architektur)

    Library: React 18/19

    UI-Komponenten: Ant Design (aktuell im Einsatz) / Übergang zu Shadcn/ui + Tailwind CSS (für maximale Flexibilität)

    State Management:

    Server-State: TanStack Query v5 (Caching, Auto-Refresh, Typsicherheit)

    UI-State: Zustand (Minimalistisches Global State Management)

    Data & Infrastructure

    Datenbank: PostgreSQL 16

    Caching: Redis 7

    Background Jobs: BullMQ (Redis-basierte Queue)

    Storage: MinIO / S3-kompatibel

    Tooling & Qualitätssicherung

    Monorepo-Management: Turbo (Turborepo)

    Testing:

    Unit/Integration: Vitest (extrem schnell, moderne Jest-Alternative)

    E2E: Playwright (für Browser-Tests)

    Linting/Formatting: ESLint + Prettier (mit langfristiger Tendenz zu Biome)

    Zum Testen und Anschauen des jetzigen Zustandes


    GitHub - Avatarsia/OpenXE at rework
    OpenXE - Free Open Source ERP based on Xentral. Contribute to Avatarsia/OpenXE development by creating an account on GitHub.
    github.com

    im Ordner "/modern/"

    docker-compose up --build -d


    localhost:3001/de/login


    api unter port 3000


    openxe@local.de

    admin123

  • Lexan

    Changed the title of the thread from “Feedback erwünscht” to “Framwork Vorschlag - Feedback erwünscht”.
  • Ich finde OpenXE sehr interessant, aber es fehlen mir schlichtweg passende Anbindungen.
    Als Laie kann ich das leider nicht beurteilen, inwiefern deine Arbeit für meine fehlenden Eigenschaften von Nutzen sein könnte oder ist.

    Dennoch finde ich dein Einsatz es sehr lobenswert.
    Das so nebenbei.🙏 :thumbup:

  • Hi, danke für dein Feedback. Ja, es geht eigentlich auch hauptsächlich darum, dass die Developer dann am Ende des Tages mitmachen. Die Anbindungen kommen dann nach und nach.Ich will halt keinen Alleingang machen, wo es hinterher heißt, nee, so können wir nicht mehr damit arbeiten und das macht keinen Sinn.

  • Ich habe ja schon auf Github etwas dazu geschrieben, will das aber der Vollständigkeit halber hier auch nochmal kurz schreiben:


    Ich finde deine Bemühungen auch echt klasse. Zumal man mit einem kleinen Proof-of-Concept auch mehr erreicht als mit vielen langen Diskussionen... wobei "klein" jetzt für deine Arbeiten auch nicht mehr ganz passend ist :)


    Bei deinem Ansatz gibt es einen kompletten Technologie-Wechsel. Kein PHP mehr, überwiegend JavaScript/TypeScript. Mal davon abgesehen, dass ich kein großer Fan davon bin, bedeutet das natürlich einen vollständigen Code-Rewrite inkl. den ganzen neuen Erweiterungen. Also auch der ganze "neue" Code seit dem Fork von Xentral muss ein weiteres mal "geschrieben" werden. Das zudem in einer Sprache, die zumindest für einige der aktuellen Kernentwickler nicht in der Komfort-Zone liegt. Es braucht also nicht nur den Willen sondern auch eine gewisse Lernphase.

    Aktuell geplante und laufende Entwicklungen müssen entweder pausieren oder doppelt erfolgen (in PHP und in TS). Da bestehender Code nicht weitergenutzt werden kann, würde die neue Fassung sehr viel Zeit verschlingen bis sie auch nur ansatzweise an die aktuelle Version heran reicht.


    Ich sehe gerade nicht, dass die Vorteile deines Ansatzes die Nachteile überwiegen. Zudem frage ich mal ganz vorsichtig: Wer bezahlt das alles? Ich investiere auch viele Stunden in ein OpenSource-Projekt ohne finanzielle Gegenleistung, aber das geht natürlich nur bis zu einem gewissen Grad. Der Kühlschrank muss ja auch irgendwie gefüllt werden. Ohne, dass hier Investoren bereit sind Geld hinzulegen würde sich so ein vollständiger Umbau vermutlich über viele Monate/Jahre hinziehen - eben ohne einen Zwischenstand der für die Mehrheit nutzbar wäre.


    Da ich aber auch sehe, dass hier Handlungsbedarf besteht, möchte ich zumindest einen Gegenvorschlag machen:
    Mit dem Einsatz des PHP-Frameworks Symfony könnten wir den bestehenden Code schrittweise modernisieren. Das "Backend" könnte nach und nach auf die Verwendung von Symfony umgestellt werden, Modul für Modul modernisiert werden ohne dass es längere Zeiträume gibt in der die Codebasis nicht produktiv genutzt werden kann. Das UI kann ebenfalls durch die Verwendung eines modernen Template-Systems wie Twig überarbeitet werden, womit auch dein ursprüngliches Problem adressiert werden kann. Statt einem vollständigen Umbau auf React oder Vue, werden einzelne Komponenten je nach Komplexität und Dringlichkeit mittels Symfony UX "aufgewertet", durch ein Vue oder React Component ersetzt oder auch erstmal unverändert weitergenutzt. Mit diesem Ansatz erhalten wir ebenfalls viele Vorteile eines modernen Frameworks, bleiben aber in der PHP-Welt und können die Umstellung ohne harten Bruch vornehmen.

  • Also grundsätzlich schließe ich mich Andi an, einen derart krassen Wechsel halte ich für völlig unrealistisch. Ich habe auch keine Vorstellung wie das überhaupt umzusetzen sein soll. Da kann man wahrscheinlich gleich ein neues System anfangen.


    Was mir viel mehr auf den Fingern brennt ist die Verbesserung der vorhandenen Codebasis. Dort ist alles total kompliziert und an vielen Stellen doppelt und dreifach implementiert. Das ist eigentlich der Grund, warum das Programmieren mit OpenXE so schwierig ist. Mir wäre es lieb wenn wir an der Stelle ansetzen und den Code derart optimieren, dass z.B. das Hinzufügen einer Spalte oder einer neuen Schnittstelle nicht jedes mal in endlose Handarbeit und Datei-Archäologie ausartet. Gerne können wir dabei auch schauen ob wir an der einen oder anderen Stelle vorhandenen Code auf ein neues Framework setzen können, wenn es uns konkret hilft. Dann sollten wir aber nicht das neue Framework dazubasteln, sondern wirklich konsequent migrieren und alten Code komplett entfernen.


    Ich würde sogar so weit gehen und sagen dass wir auch komplett ohne neue Frameworks durch strukturiertes Aufräumen des vorhandenen Codes sehr starke Verbesserungen erreichen können, die uns greifbar und zeitnah echten Mehrwert beim Entwickeln bieten.

  • Gerne:

    • Jedes Modul hat eigenen Code für die Erzeugung der Listenansichten die mit dem Code in class.yui zusammenarbeitet, die Anpassung ist aufwändig und fehleranfälli. Es wird HTML- und teilweise Javascript-Code in oder vor den SQL-Funktionen erzeugt, durch die Datenbankabfrage durchgeschleust und dann im Frontend ausgegeben.
      • Abstraktion der Listenansichten und Vereinheitlichung, damit in den Modulen flexibel und einfach Sichten erzeugt werden können
    • Es existieren Module mit .tpl-Masken, andere sind über das Widget-System implementiert, andere über Javascript, andere über eine interne Erzeugungsfunktion für Masken (z.B. Shop). Das Widget-System ist unklar, die Programmierung darin total aufwändig, z.B. zum Anlegen eines Feldes in der Maske
      • Vereinheitlichung der Maskensysteme auf einen Systemstandard, der einfach und übersichtlich gestaltet ist
    • Es existieren (mindestens) 3 Codegeneration, die nicht zusammengeführt wurden: Module, class.erpapi, Code in /classes, jedes Modul ist irgendwie unterschiedlich umgesetzt
      • Festlegung einer einheitlichen Struktur und Trennung von Modulfrontendcode, Funktionscode und Core-Systemcode
    • Das Widget-System verwendet für den Datenbankzugriff die objectapi, diese scheint aus automatisch generiertem Code zu bestehen, der aber teilweise manuell angepasst wurde. Das Codegenerierungsystem ist unbekannt. Änderungen erfordern pro Datenfeld jeweils mehrere Änderungen in unterschiedlichen Dateien. Jedes Modul arbeitet mit eigenen SQL-Befehlen, überall ist individueller Code für den Zugriff auf die Datenbank implementiert
      • Trennen von Funktionen und Datenbankzugriff, einheitliche Schnittstelle in die DB über ein Business-Model
    • Ein eigener Eintrag für das Trauerspiel class.erpapi.php
      • Aufräumen, Entheddern, in ordentliche Klassenstrukturen gliedern
    • Ein eigener Eintrag für das Trauerspiel class.yui.php
      • Aufräumen, Entheddern, in ordentliche Klassenstrukturen gliedern

    Das sind die meiner Meinung nach schlimmsten Dinge, die das Entwickeln so extrem schwierig machen, evtl. kann Andi noch dazu etwas anmerken und ergänzen.

  • Was mir noch einfällt:

    - Eine Menge von Code der darauf abzielt optionale Module (separat zu erwerbern) zu integrieren und wenn das Modul fehlt oder da ist aber deaktiviert ist oder da ist und aktiviert ist jeweils etwas anders macht

    - Unmengen von JS-Code der inline in PHP-Dateien erzeugt wird, oft noch mit PHP-Variablen ergänzt wird und dann mittels $app->Tpl->Set in eine Template-Variable geschrieben wird. Wann welche JS-Code nun im Output vorhanden ist und ob der auch was bewirkt oder oder Target fehlt ist sehr häufig nur mit aufwendiger Suche nachvollziehbar

    - Zahlreiche DB-Querys mit potentiell gefährlichen sprintf oder sowas... ob die dort injizierte Variable zuvor korrekt escaped oder geprüft wurde... erstmal suchen, also potentiell weiterhin gefährlich :)

    - Daten werden oft in wirren Arrays umhergereicht... was da drin steckt oder stecken muss und was nun der Unterschied zwischen $data['ustfrei'], $data['umsatzsteuer'] und $data['steuersatz'] ist erfordert ebenfalls sehr viel Recherchearbeit

    - Das Ganze Cronjob/Prozessstarter-System ist "historisch gewachsen"... das ist die einzige Ausrede die mir dafür einfällt


    Und wenn ich noch länger nachdenke fällt mir sicher auch noch mehr ein...


    Für mich ist es relativ eindeutig, dass egal was wir unternehmen, der Umbau "nebenher" laufen muss. Wir können uns da natürlich organsieren und die Themen nacheinander angehen oder verschiedene Personen arbeiten an unterschiedlichen Themen gleichzeitig. Aber das System muss während des Umbaus lauffähig bleiben, anders sehe ich nicht wie das funktionieren soll.


    Warum habe ich symfony vorgeschlagen? Natürlich weil ich damit schon gearbeitet habe und es kenne. Aber auch weil ich oft bei den von mir und Alex erwähnten Punkte ja bereits überlegt habe wie man es besser machen könnte und dachte: hätte ich jetzt symfony wüsste ich einen guten Weg. Das ist sicherlich nicht immer das non-plus-ultra, aber symfony hat ein breites Spektrum mit gut durchdachten Ansätzen und es hat für mich ein schlüssiges Gesamtkonzept. Am Ende wirkt zumindest der Großteil des Codes wie aus einem Guss.


    Ich mache gerade mit symfony auch ein paar Trockenübungen an OpenXE um mal zu sehen wie das gehen könnte. Ich kann da momentan nicht super viel Zeit reinstecken, daher werde ich wohl noch ein paar Tage brauchen bis ich mehr dazu sagen kann. Aber der erste Test, symfony einfach vor das ganze OpenXE zu schalten war schonmal erfolgreich und ich kann alle Anfragen durch symfony routen (inkl. ErrorHandler und WebProfiler) und zudem Symfony-Services in OpenXE nutzen (bspw. Twig-Templates oder Doctrine). Dazu gerne in ein paar Tagen mehr.

  • ich habe mir deinen Framework-Vorschlag mal kurz angeschaut. Grundsätzlich finde ich die Anpassungen echt top – moderner Techstack mit NestJS, Next.js, Prisma und Co. sieht sehr solide aus und adressiert viele der aktuellen Pain Points.

    Was mir sofort aufgefallen ist: Die Node.js-Versionen (seit 2023/2024) und die Postgres-Version (ebenfalls seit 2023) sind End-of-Life. Das sollten wir definitiv auf die neuesten LTS-Versionen updaten, um Security und Support zu gewährleisten.

    Besonders positiv: Die Möglichkeit für individuelle Anpassungen ohne ständige Upstream-Konflikte. Persönlich sind mir Updates aus dem Upstream (egal ob Frontend, Funktionalität oder DB) immer die Hölle wegen der lokalen Mods – eine saubere Trennung davon wäre super hilfreich und würde viel Frust sparen.


  • 1. Quantitative Übersicht des Ist-Zustands


    BereichDatei(en)Umfang
    class.erpapi.php class.erpapi.php39.520 Zeilen, 1.038+ Methoden
    class.yui.php class.yui.php15.983 Zeilen, 77 Methoden
    Page-Module (www/pages/)147 Dateien + 1.180 .tpl-TemplatesGrößte: api.php (618 KB), artikel.php (461 KB), auftrag.php (331 KB)
    ObjectAPI (www/objectapi/mysql/_gen/)183 generierte Dateienz.B. object.gen.artikel.php (1.511 Zeilen, 86 KB)
    Widgets (www/widgets/)89 Widget-Dateien + 121 generiertez.B. widget.shopexport.php (49 KB)
    Neue Module (classes/Modules/)125 ModuleHeterogene Struktur, 1.412 Dateien gesamt
    Cronjobs81 Dateienstarter.php, starter2.php + 79 Task-Skripte
  • 2. Befund zu jedem Kritikpunkt



    2.1 HTML/JS-Code in SQL-Abfragen (Listenansichten + class.yui)

    Bestätigt — Schweregrad: Kritisch

    In der TableSearch()-Methode jedes Moduls wird HTML direkt in SQL-CONCAT()-Aufrufen erzeugt. Konkretes Beispiel aus

    artikel.php:94:

    Code
    sql
    
    
    
    SELECT ... CONCAT('<table cellpadding=0 cellspacing=0><tr><td nowrap>  <a href="#" onclick="editeigenschaft(',ew.id,')">')  ...
    • HTML (<img>, <input>, <table>, <a>) wird direkt in SQL generiert
    • JavaScript-Event-Handler (onclick="...") werden in SQL-Strings eingebettet
    • Formular-Elemente (Checkboxen, Text-Inputs) entstehen als SQL-Spalten:
    Code
    sql
    
    
    
    CONCAT('<input type="checkbox" name="artikelmarkiert[',a.id,']"   value="1">')  AS wahl

    Dieses Muster wiederholt sich in praktisch jedem der 147 Page-Module. Die gesamte Listenansichten-Logik ist in class.yui.php mit fest verdrahteter SQL/HTML-Mischung verschränkt.

    2.2 Fragmentierte Maskensysteme (.tpl, Widgets, JS, interne Generierung)

    Bestätigt — Schweregrad: Hoch

    Es existieren mindestens 4 verschiedene UI-Rendering-Ansätze, die parallel genutzt werden:

    SystemOrtBeispiel
    TPL-Templateswww/pages/content/*.tpl1.180+ Template-Dateien, einfache Platzhalter-Substitution
    Widget-Systemwww/widgets/widget.*.php89 Widget-Dateien mit Form-Handler, erben von _gen/widget.gen.*.php
    Inline-PHP-HTMLDirekt in www/pages/*.phpz.B. $app->Tpl->Set('ARTIKELBILD', '<img src=...')
    JS-Frontendwww/js/3.558 Dateien, teilweise direkt aus PHP injiziert

    Die Widget-Dateien zeigen exemplarisch das Problem:

    widget.artikel.php benötigt 686 Zeilen allein für die Formular-Definition eines Artikels, mit ~44 AutoComplete-Registrierungen und ~28 ReplaceFunction-Zuweisungen, alles imperativ und manuell.

    2.3 Mindestens 3 nicht zusammengeführte Code-Generierungen

    Bestätigt — Schweregrad: Hoch

    Die drei Code-Ebenen sind klar identifizierbar:

    1. www/pages/_gen/*.php — Generierte Basis-Klassen für Page-Module (z.B. GenArtikel)
    2. www/objectapi/mysql/_gen/object.gen.*.php — 183 Data-Access-Klassen mit CRUD-Methoden
    3. www/widgets/_gen/widget.gen.*.php — 121 generierte Widget-Basis-Klassen

    Dazu kommt die neuere Struktur in classes/Modules/ (125 Module mit eigenem Aufbau) und classes/Components/ (352 Dateien).

    Jede Generation folgt einem anderen Muster, und das Codegenerierungs-Tool ist unbekannt — die generierten Dateien tragen keine Metadaten über den Generator.

    2.4 ObjectAPI: Generierter Code ohne Prepared Statements

    Bestätigt — Schweregrad: Kritisch (Sicherheit)

    Die ObjectAPI-Dateien (z.B.

    object.gen.artikel.php) verwenden durchweg String-Interpolation für SQL:

    • Kein einziges Prepared Statement in den 183 generierten Dateien
    • Jede Klasse hat ein eigenes Select()/Create()/Update()/Delete(), das alle Felder manuell in Properties, SQL-Spalten und zurück mappt (für artikel: ~250 Felder, 500+ Zeilen reines Mapping)
    • Kein real_escape_string(), kein PDO, kein Parameterized Query

    2.5 class.erpapi.php — "Das Trauerspiel"

    Bestätigt — Schweregrad: Kritisch

    class.erpapi.php mit 39.520 Zeilen und 1.038+ Methoden in einer einzigen Klasse erpAPI:

    • God Object Antipattern: Eine Klasse für Cronjobs, Navigation, Mail, Belege, Artikel, Shop-Integration, PDF-Generierung, CSV-Export, Lagerverwaltung, Steuerberechnung, Hook-System, Benutzerverwaltung
    • Methoden wie Belegeexport() (175 Zeilen), NavigationHooks() (92 Zeilen) sind geschäftskritisch, aber undokumentiert
    • Enthält zahlreiche @deprecated und @refactor Annotationen die nie umgesetzt wurden
    • Viele Methoden delegieren nur an neuere Module, existieren aber weiterhin als Wrapper

    2.6 class.yui.php — "Das Trauerspiel"

    Bestätigt — Schweregrad: Kritisch

    class.yui.php mit 15.983 Zeilen und 77 Methoden:

    • AARLGPositionen()1.633 Zeilen (Zeile 1451–3084), eine einzige Methode
    • AARLGEditable()426 Zeilen (Zeile 404–830)
    • Generiert HTML-Tabellen, JavaScript-Eventhandler und jQuery-UI-Widgets direkt in PHP
    • IconsSQL() — 221 Zeilen reine SQL-CASE-Expressions für Statusicons
    • Jedes Modul ruft $this->app->YUI->... hundertfach auf — enge Kopplung

    2.7 Optionale Module: Feature-Flags verstreut im Code

    Bestätigt — Schweregrad: Mittel

    Das Pattern $app->erp->ModulVorhanden('...') wird durchweg verwendet, z.B. in

    widget.artikel.php:266:

    Code
    php
    
    
    
    if(!$this->app->erp->ModulVorhanden('formeln')) {    $this->app->Tpl->Set('VORFORMELN','<!--');    $this->app->Tpl->Set('NACHFORMELN','-->');
    
    }

    HTML-Kommentare (<!-- -->) werden als Toggle-Mechanismus für UI-Bereiche verwendet — fragil und fehleranfällig.

    2.8 Inline-JS in PHP mit Template-Variablen

    Bestätigt — Schweregrad: Hoch

    In jeder TableSearch()-Methode: JavaScript wird per PHP-Stringkonkatenation generiert und via $app->Tpl->Add('JAVASCRIPT', ...) injiziert. Beispiel

    artikel.php:121-135:

    Code
    php
    
    
    
    $this->app->Tpl->Add('JAVASCRIPT', '  function fnFilterColumn' . $r . ' ( i ) {    if(oMoreData' . $r . $name . '==1)      oMoreData' . $r . $name . ' = 0;    else      oMoreData' . $r . $name . ' = 1;    $(\'#' . $name . '\').dataTable().fnFilter(      \'\', i, 0, 0);  }');

    Dies ist ein massives Nachvollziehbarkeits-Problem, da man nicht weiß, welcher JS-Code im finalen Output landet.

    2.9 SQL-Injection-Risiken durch sprintf und Variablen-Interpolation

    Bestätigt — Schweregrad: Kritisch (Sicherheit)

    Zahlreiche Queries ohne Escaping bzw. mit unzureichendem Schutz:

    Im Widget-Code wird $id durchaus per $app->Secure->GetGET('id') geholt, aber ob die Secure-Klasse ausreichend escaped, muss pro Aufruf manuell verifiziert werden. Es gibt keine systematische Parameterisierung.

    2.10 Unklare Daten-Arrays

    Bestätigt — Schweregrad: Mittel

    Inkonsistente Namensgebung in Daten-Arrays ($data['ustfrei'], $data['umsatzsteuer'], $data['steuersatz']) — es gibt keine DTOs, keine Value Objects, keine Typisierung. Daten werden ausschließlich als assoziative Arrays herumgereicht — ohne Dokumentation, was enthalten sein muss.

    2.11 Cronjob/Prozessstarter-System "historisch gewachsen"

    Bestätigt — Schweregrad: Mittel

    Zwei parallele Starter (

    starter.php + starter2.php, jeweils ~267 Zeilen), die:

    • Eine eigene Mini-Application (app_t extends ApplicationCore) instanziieren
    • Direkt exec() aufrufen um PHP-Prozesse zu starten
    • Mutex/Locking über Datenbank-Felder (mutexcounter) implementieren
    • Kein echtes Queue-System, kein Error-Recovery, kein Retry-Mechanismus
  • 3. Optimierungsoptionen



    IMPORTANT

    Jede Optimierung muss nebenher erfolgen — das System muss während des Umbaus lauffähig bleiben. Die Optionen sind nach Impact/Machbarkeit priorisiert.

    Option A: Strangler-Fig-Pattern mit Symfony als Fassade

    Der im Forum vorgeschlagene Ansatz. Symfony wird vor das bestehende System geschaltet (bereits als Proof-of-Concept getestet laut Foren-Post).

    ProContra
    Alle Requests durch Symfony routbar (bestätigt)Sehr hohes Lernkurven-Risiko wenn nicht alle Entwickler Symfony kennen
    Doctrine als ORM löst SQL-Injection und ObjectAPI-ProblemeParallelbetrieb alte+neue Architektur = doppelte Wartung
    Twig-Templates lösen das Maskensystem-ProblemLangwieriger Migrationspfad (Monate bis Jahre)
    ErrorHandler + WebProfiler sofort nutzbarSymfony-Versionsupgrades werden zur zusätzlichen Abhängigkeit

    Option B: Schrittweise Modernisierung ohne Framework-Wechsel

    Fokus auf die kritischsten Probleme, innerhalb der bestehenden Architektur:

    B1. Prepared Statements einführen (Sicherheit — Priorität 1)

    • class.mysql.php um PDO-basierte Prepared Statements erweitern
    • ObjectAPI-Generator (falls auffindbar) anpassen oder die 183 generierten Dateien mit einem Skript auf Parameterized Queries umschreiben
    • Schrittweise Migration: Zuerst alle user-input-nahen Queries

    B2. class.erpapi.php entflechten (Priorität 2)

    • Zunächst alle 1.038 Methoden kategorisieren (viele haben bereits @refactor-Tags)
    • In Domain-spezifische Service-Klassen aufteilen (Belegwesen, Artikel, Lager, Shop, etc.)
    • Facade-Pattern: erpAPI delegiert initial nur weiter, wird dann sukzessive abgebaut

    B3. Listenansichten abstrahieren (Priorität 3)

    • Eine einheitliche TableSearch-Konfiguration (JSON/Array-basiert statt Code)
    • HTML/JS-Generierung aus SQL entfernen, in einen Renderer auslagern
    • class.yui.php schrittweise in spezialisierte UI-Komponenten aufteilen

    B4. Template-System vereinheitlichen (Priorität 4)

    • Entscheidung für einen Template-Ansatz (Twig, bestehende .tpl, oder Blade)
    • Widget-System refaktorisieren: Form-Definition per Konfiguration statt imperativem Code

    B5. Cronjobs modernisieren (Priorität 5)

    • Message-Queue-System (Symfony Messenger, RabbitMQ, oder einfaches DB-basiertes Queue)
    • Echter Mutex (File-Locks oder Advisory Locks statt DB-Counter)
    • Einheitlicher Worker-Prozess statt pro-Task exec()

    Option C: Domain-Driven Redesign (Langfristiger Ansatz)

    Die bereits vorhandene classes/Modules/-Struktur als Basis nehmen und konsequent erweitern:

    • Repository-Pattern statt direkte SQL-Queries
    • Business-Model-Layer zwischen DB und UI
    • Event-System statt Feature-Flag-Prüfungen (ModulVorhanden)
    • Klare API-Contracts zwischen Modulen
  • ich habe mir deinen Framework-Vorschlag mal kurz angeschaut. Grundsätzlich finde ich die Anpassungen echt top – moderner Techstack mit NestJS, Next.js, Prisma und Co. sieht sehr solide aus und adressiert viele der aktuellen Pain Points.

    Was mir sofort aufgefallen ist: Die Node.js-Versionen (seit 2023/2024) und die Postgres-Version (ebenfalls seit 2023) sind End-of-Life. Das sollten wir definitiv auf die neuesten LTS-Versionen updaten, um Security und Support zu gewährleisten.

    Besonders positiv: Die Möglichkeit für individuelle Anpassungen ohne ständige Upstream-Konflikte. Persönlich sind mir Updates aus dem Upstream (egal ob Frontend, Funktionalität oder DB) immer die Hölle wegen der lokalen Mods – eine saubere Trennung davon wäre super hilfreich und würde viel Frust sparen.

    also generell wäre ich ja dabei das weiter auszuführen, aber auch zu 2. könnte die nummer n bissl zu groß sein

    ich meine ja die basis ist nebenbei in einer woche entstanden aber dennoch braucht das ja einiges an resourcen und ablauf überprüfung

  • Danke für die ausführliche Analyse, auch wenn da jetzt für mich erstmal nicht viel neues drin steht.


    Hinsichtlich deines Vorschlags würde ich ungeachtet aller subjektiven Empfindungen und Beliebtheiten etc. einfach mal vermuten, dass wenn man den gleichen Aufwand der für einen kompletten Rewrite nötig wäre in eine Verbesserung des bestehenden Systems (egal ob mit Symfony, mit was anderem oder ohne Framework) investiert, vermutlich am Ende mehr raus kommt... Kann ich nicht beweisen, ist einfach mein Gefühl :)


    Bezüglich deiner drei genannten Optionen würde ich aber gerne noch etwas ergänzen:


    Die unter Option A genannten Pro- und Contra-Argumente treffen meiner Meinung nach so nicht alleine für Symfony zu. Die Lernkurve wird bspw. bei einem Wechsel von PHP zu JS/TS vermutlich noch viel steiler ausfallen und die Lernkurve ist bei dem derzeitigen Code-Stand auch alles andere als gering.


    Eine zusätzliche Abhängigkeit erhält man mit jeder Art von Lib/Framework. Hier spielt aber gerade Symfony eine Stärke gegenüber bspw. Laravel aus. Die aktuelle LTS Version von Symfony (7.4) wird bis 11/2029 mit Sicherheitsupdates versorgt. Das dürfte erstmal für genügend Ruhe sorgen.


    Dass das Ganze langwierig sein wird haben wir vermutlich auch immer - egal für welchen Weg wir uns entscheiden. Symfony ist aber sehr modular aufgebaut und ich kann Teile davon nutzen und andere wiederum nicht. Ich wähle erstmal nur die Komponenten aus, die mir wirklich weiterhelfen und lasse den Rest so wie es ist. Wenn diese Baustelle dann abgeschlossen ist kann ich die nächste angehen. Damit kann ich dann auch den Parallelbetrieb von verschiedenen Architekturen deutlich reduzieren.


    Dein Post erweckt für mich den Eindruck, dass die Optionen A, B und C (und D wenn wir deinen Ansatz noch dazu nehmen) verschiedene Wege darstellen und wir uns dazwischen entscheiden müssen. Das sehe ich aber in vielen Aspekten nicht so. Bei einem vollständigen Wechsel zu Symfony, wäre bspw. die Option C quasi "enthalten". Bei Option B kann man für jeden Punkt durchaus die von Symfony "angedachte" Lösung benutzen und eben modular ohne den Rest des Symfony-Frameworks verwenden. Und bei Option A kann man die Umstellung natürlich mit der unter Option B genannten Priorisierung starten. Für mich spielt das also alles ineinander.

  • Okay ein wenig hintergrundfutter wieso ich das so gepostet habe.
    Ihr habt von der Materie deutlich mehr Ahnung als ich, entsprechend gebe ich euch meine Grundlage (Analyse) mit auf der ich arbeite damit Ihr offensichtliche Fehltritte bzw, fehlannahmen gleich kommentieren könnt.

    Tatsächlich waren Option A,B &C nur Ansätze wo man als erstes Starten kann, am ende sollten Sie kombiniert werden.
    Option "D" wäre eine komplette Umstellung, hatte auch nicht mehr wirklich was mit der Original Code Grundlage zu tun.

    Ich wollte einfach mal die Diskussion ins rollen bringen und wenn man sich auf was einigen kann entsprechend n bissl ausprobieren.

    EDIT: Achja, 3 Beiträge weil man max. 10.000 Zeichen Posten kann :D

  • Ja klar, das hilft auf jeden Fall! Ich wollte das auch lediglich ergänzen/klarstellen/kommentieren wie ich das sehe.


    Ich finde es wirklich gut, dass wir uns da Gedanken zu machen. Früher oder später werden uns sonst auch gewisse Dinge einholen und dann wird es Stress... Ich sage nur "die Zukunft von jQuery" :D

  • kleines update.


    │ Phase │ Topic │ Status │

    │ 0 │ PHP 8.5 Merge │ Done │

    │ 1 │ DB layer — Prepared Statements │ Next │

    │ 2 │ Decompose class.erpapi.php (39k lines) │ Blocked by 1 │

    │ 3 │ Replace ObjectAPI with Repository layer │ Blocked by 1 │

    │ 4 │ Abstract list views (TableSearch) │ Blocked by 2+3 │

    │ 5 │ Split class.yui.php (16k lines) │ Blocked by 2+4 │

    │ 6 │ Unified form/mask system │ Blocked by 5+3 │

    │ 7 │ Eliminate inline JS │ Blocked by 4+6 │

    │ 8 │ Standardize module structure │ Blocked by 2+3 │

    │ 9 │ Optional modules / feature flags │ Blocked by 8 │

    │ 10 │ Modernize cronjob system │ Blocked by 2

    das habe ich jetzt als roadmap.
    das ganze ist in meinem repo unter dem branch development, und phase 1 ist gerade in arbeit

  • Ich habe mal in meine Repository einen Branch "symfony" gepusht. Dort habe ich verschiedene Aspekte ausprobiert und mal unterschiedliche "Ausbaustufen" gebastelt.


    Das "Passwort vergessen"-Formular ist quasi komplett auf Symfony umgestellt, mit Controller, Form, Twig-Templates, Doctrine-Entities, usw.

    Ich habe einen LegacyController implementiert der das gesamte "alte" System durchleiten kann. Es sollte also im Wesentlichen alles bestehende weiter laufen.


    Ich habe sehr viele "alte" Klassen in composer integriert um einen einzigen Autoloader zu bekommen der funktioniert und damit hoffentlich die meisten include_once überflüssig macht. Einige zentrale Klassen habe ich auch bereits so umgebaut, dass sie mit der Symfony-DependencyInjection funktionieren und als Services zur Verfügung stehen.


    Das "welcome"-Module habe ich auf Doctrine umgestellt mit named Parameters in den SQL-Abfragen. Einige Templates habe ich auf Twig umgestellt und somit den Anteil an HTML-Code in PHP reduziert. Bei Funktionen die vermutlich ganz wegfallen werden habe ich mich versucht etwas zu bremsen.


    Den Umbau auf Doctrine mit named Parameters bekommt die KI sehr gut hin, wenn man die Aufgabe in kleine Häppchen herunterbricht und auf Tokenlimits achtet. Wann immer die erpapi ins Spiel kommt, winken die meisten Modelle mit der weißen Fahne oder der Output ist unbrauchbar :)


    Ihr könnt ja auch gerne mal in meinen Branch reinschauen... es ist aber eher eine Spielwiese als ein "Konzept". Mir ging es erstmal darum herauszufinden was gut funktioniert, was mit gefällt und was eher nicht.

  • Ich habe jetzt mal in dein ( Lexan) Repository reingeschaut. Sehe aber bisher nur zahlreiche .md Files... ist das so gedacht oder mache ich was falsch?


    Was mir dabei aber aufgefallen ist: Du möchtest die prepared Statements mit der mysql.class.php umsetzen, richtig? Davon würde ich wirklich abraten. Es gibt bereits eine wesentlich modernere "Database" Klasse die man über den Container bekommen kann. Wird bisher nur wenig genutzt, kann aber viel mehr.

    Allerdings frage ich mich dann auch ob man nicht direkt auf Doctrine geht. Es muss ja nicht direkt der Schritt zum ORM sein, aber der Doctrine DBAL scheint mir eigentlich nur Vorteile zu haben. Bei solch zentralen Dingen bin ich immer eher ein Fan von Standards als von Eigenbräu.

    Was denkst du?

Participate now!

Don’t have an account yet? Register yourself now and be a part of our community!