2026-06-23 09:53:19 +00:00
|
|
|
# Backend — Laravel 10
|
|
|
|
|
|
|
|
|
|
## Module pattern
|
|
|
|
|
Every feature lives in `app/Modules/<Name>/`:
|
|
|
|
|
- `Controllers/<Name>Controller.php` — thin: authorize → DTO → action → resource
|
|
|
|
|
- `Actions/Create<Name>Action.php` — handle(DTO): Model
|
|
|
|
|
- `Actions/Update<Name>Action.php` — handle(Model, DTO): Model
|
|
|
|
|
- `Models/<Name>.php` — Eloquent model
|
|
|
|
|
- `Resources/<Name>Resource.php` — explicit field list, no `$this->resource`
|
|
|
|
|
- `DTOs/<Name>Data.php` — readonly constructor + static `fromRequest()`
|
|
|
|
|
- `Requests/Create<Name>Request.php` / `Update<Name>Request.php`
|
|
|
|
|
- `Policies/<Name>Policy.php`
|
|
|
|
|
|
|
|
|
|
## Commands
|
|
|
|
|
```
|
|
|
|
|
composer test # Pest, SQLite in-memory
|
2026-07-18 09:34:18 +00:00
|
|
|
composer static-analysis # pint --test + phpstan + phpmd (user do the static code analysis manually)
|
2026-06-23 09:53:19 +00:00
|
|
|
php artisan migrate # run migrations (against Docker MySQL)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## DB schema
|
|
|
|
|
- `users`: id, name, email, password, role(enum:admin|staff), timestamps
|
|
|
|
|
- `clients`: id, client_number(unique), name, notes(JSON), timestamps
|
|
|
|
|
- `history_entries`: id, client_id(FK), type(enum), body(text), author_id(FK), updated_by(FK nullable), deleted_at, timestamps
|
|
|
|
|
|
|
|
|
|
## Auth
|
|
|
|
|
- Sanctum SPA cookie sessions — `EnsureFrontendRequestsAreStateful` on `api` middleware group
|
|
|
|
|
- Filament: `web` guard, `/admin/login`
|
|
|
|
|
- No Passport, no tokens
|
|
|
|
|
|
|
|
|
|
## API conventions
|
|
|
|
|
- Resources always wrap in `data` key (JsonResource default)
|
|
|
|
|
- Paginated lists: `data[]` + `meta.total` etc.
|
|
|
|
|
- 201 on create, 200 on update, 204 on delete
|