Files
mareike/.ai/conventions.md
2026-04-25 16:50:32 +02:00

72 lines
2.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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`
---
## 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>`