Files
mareike/.ai/conventions.md

3.6 KiB
Raw Blame History

Projektkonventionen

Architektur: Actions (Request-Command-Response)

Jede fachliche Operation wird in eine eigene Action ausgelagert, die aus drei Klassen besteht. Pfad: app/Domains/{Domain}/Actions/{ActionName}/

Struktur

{ActionName}Request.php → Eingabedaten (Konstruktor oder Factory-Methoden) {ActionName}Command.php → Logik, ruft execute(): {ActionName}Response auf {ActionName}Response.php → Rückgabedaten (public Properties)

Regeln

  • Der Controller enthält keine fachliche Logik nur Absicherung, Action-Aufruf und HTTP-Response
  • Commands sind nicht statisch und werden immer instanziiert
  • Hat ein Request mehrere Varianten, werden Factory-Methoden (forX()) statt mehrerer Konstruktoren verwendet
  • Aufrufreihenfolge im Controller: new Request → new Command(request) → command->execute() → Response verwenden

Controller

  • Alle Controller erben von App\Scopes\CommonController

  • CommonController stellt folgende Repositories bereit (keine eigene Instanziierung nötig):

    • $this->eventParticipantsEventParticipantRepository
    • $this->eventsEventRepository
    • $this->invoicesInvoiceRepository
    • $this->costUnitsCostUnitRepository
    • $this->usersUserRepository
    • $this->tenant → aktueller Tenant
  • Die Controller besitzen ausschließlich eine __invoke() - Funktion

  • Für die Speichern-Actions werden separate Controller-Klassen erstellt (z. B. StoreEventParticipantController)


Repositories

  • Datenbankzugriffe gehören immer ins Repository, nie direkt in Controller oder Actions
  • Sicherheitschecks (z. B. „gehört diese Teilnahme dem eingeloggten User?") werden als eigene Repository-Methoden gekapselt
  • Tenant-Filter: app('tenant')->slug
  • Eingeloggter User: auth()->user()

Models / Ressourcen

  • Models erben von App\Scopes\InstancedModel (mit globalem SiteScope)
  • $model->toResource()->toArray($request) liefert das aufbereitete Array über die zugehörige Resource-Klasse
  • Resource-Klassen liegen in app/Resources/{ModelName}Resource.php

Tenant

  • Der aktuelle Tenant ist per app('tenant') verfügbar (gesetzt durch IdentifyTenant-Middleware)
  • Tenant-Slug: app('tenant')->slug
  • Jede tenant-spezifische DB-Abfrage filtert auf ['tenant' => app('tenant')->slug]

Routing

  • API-Routen liegen in app/Domains/{Domain}/Routes/api.php
  • Alle Routen sind in IdentifyTenant::class-Middleware gewrappt
  • Authentifizierte Routen zusätzlich in ['auth']-Middleware

Mails

  • Mails erben von Illuminate\Mail\Mailable
  • Attachments werden über Attachment::fromData(fn () => $content, $filename)->withMime(...) angehängt
  • Werden Daten sowohl in content() als auch in attachments() benötigt, wird eine private Hilfsmethode mit Lazy-Caching verwendet (einmaliges Berechnen, Ergebnis in private Property speichern)
  • Blade-Templates referenzieren Mail-Attachments per cid:-Link: <a href="cid:{{ $filename }}">...</a>

Actions

  • Die Actions sind in app/Domains/{Domain}/Actions/{ActionName}/-Verzeichnissen organisiert
  • Jede Action besitzt einen Request, einen Command und einen Response
  • Der Request besitzt auschließlich einen Konstruktor, der die notwendigen Parameter annimmt
  • Die Response-Klasse enthält ausschließlich die notwendigen Daten für die Antwort
  • Die Action-Klasse enthält die Logik für die Verarbeitung der Anfrage und die Generierung der Antwort
  • Die Logik wird in einer execute() - Funktion innerhalb des Commands impplementiert. Private Funktionen, für ausgelagerte Prozesse sind zulässig, wenn der Code damit lesbarer wird.