3.6 KiB
3.6 KiB
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 -
CommonControllerstellt folgende Repositories bereit (keine eigene Instanziierung nötig):$this->eventParticipants→EventParticipantRepository$this->events→EventRepository$this->invoices→InvoiceRepository$this->costUnits→CostUnitRepository$this->users→UserRepository$this->tenant→ aktuellerTenant
-
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 globalemSiteScope) $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 durchIdentifyTenant-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 inattachments()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.