82 lines
3.6 KiB
Markdown
82 lines
3.6 KiB
Markdown
# 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->eventParticipants` → `EventParticipantRepository`
|
||
- `$this->events` → `EventRepository`
|
||
- `$this->invoices` → `InvoiceRepository`
|
||
- `$this->costUnits` → `CostUnitRepository`
|
||
- `$this->users` → `UserRepository`
|
||
- `$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.
|