Enable Discovery debug logging for production troubleshooting
- Add DISCOVERY_LOG_LEVEL=debug - Add DISCOVERY_SHOW_PROGRESS=true - Temporary changes for debugging InitializerProcessor fixes on production
This commit is contained in:
727
docs/guides/controllers.md
Normal file
727
docs/guides/controllers.md
Normal file
@@ -0,0 +1,727 @@
|
||||
# Controller-Anleitung
|
||||
|
||||
Diese Anleitung erklärt, wie Controller im Framework funktionieren und wie Sie sie effektiv nutzen können.
|
||||
|
||||
## Was sind Controller?
|
||||
|
||||
Controller sind Klassen, die für die Verarbeitung von HTTP-Anfragen verantwortlich sind. Sie nehmen Anfragen entgegen, führen die erforderliche Geschäftslogik aus und geben Antworten zurück. Controller dienen als Vermittler zwischen den Modellen (Daten und Geschäftslogik) und den Views (Präsentationsschicht).
|
||||
|
||||
## Grundlegende Controller
|
||||
|
||||
### Erstellen eines Controllers
|
||||
|
||||
Controller werden im Verzeichnis `src/Application/Controllers` gespeichert. Ein einfacher Controller sieht wie folgt aus:
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
||||
namespace App\Application\Controllers;
|
||||
|
||||
use App\Framework\Http\Controller;
|
||||
use App\Framework\Http\Request;
|
||||
use App\Framework\Http\Response;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
public function index(Request $request): Response
|
||||
{
|
||||
return $this->view('users.index', [
|
||||
'users' => User::all()
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(Request $request, int $id): Response
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
if (!$user) {
|
||||
return $this->notFound('Benutzer nicht gefunden');
|
||||
}
|
||||
|
||||
return $this->view('users.show', [
|
||||
'user' => $user
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Controller-Basisklasse
|
||||
|
||||
Alle Controller sollten von der `App\Framework\Http\Controller`-Klasse erben, die nützliche Methoden für die Erstellung von Antworten bereitstellt:
|
||||
|
||||
```php
|
||||
// Gibt eine View zurück
|
||||
$this->view('users.index', ['users' => $users]);
|
||||
|
||||
// Gibt JSON zurück
|
||||
$this->json(['name' => 'John', 'email' => 'john@example.com']);
|
||||
|
||||
// Leitet zu einer anderen URL um
|
||||
$this->redirect('/users');
|
||||
|
||||
// Leitet zurück zur vorherigen Seite um
|
||||
$this->back();
|
||||
|
||||
// Gibt einen Fehler zurück
|
||||
$this->error('Ein Fehler ist aufgetreten', 500);
|
||||
|
||||
// Gibt einen 404-Fehler zurück
|
||||
$this->notFound('Seite nicht gefunden');
|
||||
|
||||
// Gibt einen 403-Fehler zurück
|
||||
$this->forbidden('Zugriff verweigert');
|
||||
|
||||
// Gibt eine leere Antwort zurück
|
||||
$this->noContent();
|
||||
```
|
||||
|
||||
## Anfragen verarbeiten
|
||||
|
||||
### Zugriff auf Anfragedaten
|
||||
|
||||
Sie können auf die Daten einer Anfrage über das `Request`-Objekt zugreifen:
|
||||
|
||||
```php
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
// Zugriff auf Formulardaten
|
||||
$name = $request->input('name');
|
||||
$email = $request->input('email');
|
||||
|
||||
// Zugriff auf Formulardaten mit Standardwert
|
||||
$age = $request->input('age', 18);
|
||||
|
||||
// Prüfen, ob ein Feld vorhanden ist
|
||||
if ($request->has('address')) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Zugriff auf alle Formulardaten
|
||||
$data = $request->all();
|
||||
|
||||
// Zugriff auf bestimmte Formulardaten
|
||||
$userData = $request->only(['name', 'email']);
|
||||
$nonUserData = $request->except(['name', 'email']);
|
||||
|
||||
// Zugriff auf URL-Parameter
|
||||
$page = $request->query('page', 1);
|
||||
|
||||
// Zugriff auf Dateien
|
||||
$file = $request->file('avatar');
|
||||
|
||||
// Zugriff auf Header
|
||||
$token = $request->header('Authorization');
|
||||
|
||||
// Zugriff auf Cookies
|
||||
$remember = $request->cookie('remember', false);
|
||||
|
||||
// Zugriff auf die Anfragemethode
|
||||
$method = $request->method();
|
||||
|
||||
// Prüfen, ob die Anfrage eine AJAX-Anfrage ist
|
||||
if ($request->isAjax()) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Prüfen, ob die Anfrage eine bestimmte Methode verwendet
|
||||
if ($request->isMethod('POST')) {
|
||||
// ...
|
||||
}
|
||||
|
||||
// Zugriff auf die Anfrage-URL
|
||||
$url = $request->url();
|
||||
|
||||
// Zugriff auf die vollständige Anfrage-URL mit Abfrageparametern
|
||||
$fullUrl = $request->fullUrl();
|
||||
|
||||
// Zugriff auf den Pfad der Anfrage
|
||||
$path = $request->path();
|
||||
}
|
||||
```
|
||||
|
||||
### Validierung von Anfragedaten
|
||||
|
||||
Sie können Anfragedaten direkt im Controller validieren:
|
||||
|
||||
```php
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'password' => 'required|string|min:8|confirmed',
|
||||
]);
|
||||
|
||||
// Die Validierung wurde bestanden, fahren Sie mit der Speicherung fort
|
||||
$user = User::create($request->only(['name', 'email', 'password']));
|
||||
|
||||
return $this->redirect('/users')->with('success', 'Benutzer erstellt');
|
||||
}
|
||||
```
|
||||
|
||||
Wenn die Validierung fehlschlägt, wird automatisch eine Antwort mit den Validierungsfehlern zurückgegeben. Bei einer regulären Anfrage wird der Benutzer zur vorherigen Seite umgeleitet, bei einer AJAX-Anfrage wird eine JSON-Antwort mit den Fehlern zurückgegeben.
|
||||
|
||||
Weitere Informationen zur Validierung finden Sie in der [Validierungs-Anleitung](validation.md).
|
||||
|
||||
## Antworten erstellen
|
||||
|
||||
### HTML-Antworten
|
||||
|
||||
Um eine HTML-Antwort zu erstellen, verwenden Sie die `view`-Methode:
|
||||
|
||||
```php
|
||||
public function index(): Response
|
||||
{
|
||||
$users = User::all();
|
||||
|
||||
return $this->view('users.index', [
|
||||
'users' => $users
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
Die `view`-Methode akzeptiert den Namen der View und ein Array mit Daten, die an die View übergeben werden sollen. Der Name der View entspricht dem Pfad der View-Datei relativ zum Verzeichnis `resources/views`, wobei Punkte als Verzeichnistrennzeichen verwendet werden. Im obigen Beispiel wird die Datei `resources/views/users/index.php` gerendert.
|
||||
|
||||
### JSON-Antworten
|
||||
|
||||
Um eine JSON-Antwort zu erstellen, verwenden Sie die `json`-Methode:
|
||||
|
||||
```php
|
||||
public function index(): Response
|
||||
{
|
||||
$users = User::all();
|
||||
|
||||
return $this->json([
|
||||
'users' => $users
|
||||
]);
|
||||
}
|
||||
```
|
||||
|
||||
Die `json`-Methode akzeptiert ein Array oder ein Objekt, das in JSON konvertiert werden soll, und einen optionalen HTTP-Statuscode:
|
||||
|
||||
```php
|
||||
return $this->json(['error' => 'Nicht gefunden'], 404);
|
||||
```
|
||||
|
||||
### Weiterleitungen
|
||||
|
||||
Um eine Weiterleitung zu erstellen, verwenden Sie die `redirect`-Methode:
|
||||
|
||||
```php
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
// Benutzer erstellen
|
||||
|
||||
return $this->redirect('/users');
|
||||
}
|
||||
```
|
||||
|
||||
Sie können auch zur vorherigen Seite umleiten:
|
||||
|
||||
```php
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
// Validierungsfehler
|
||||
|
||||
return $this->back();
|
||||
}
|
||||
```
|
||||
|
||||
Sie können Flash-Daten mit der Weiterleitung senden:
|
||||
|
||||
```php
|
||||
return $this->redirect('/users')
|
||||
->with('success', 'Benutzer erstellt');
|
||||
```
|
||||
|
||||
Diese Flash-Daten sind in der nächsten Anfrage über die Session verfügbar:
|
||||
|
||||
```php
|
||||
$message = $request->session()->get('success');
|
||||
```
|
||||
|
||||
### Fehlerantworten
|
||||
|
||||
Um eine Fehlerantwort zu erstellen, verwenden Sie eine der Fehlermethoden:
|
||||
|
||||
```php
|
||||
// 404 Not Found
|
||||
return $this->notFound('Benutzer nicht gefunden');
|
||||
|
||||
// 403 Forbidden
|
||||
return $this->forbidden('Sie haben keine Berechtigung, diesen Benutzer zu bearbeiten');
|
||||
|
||||
// 401 Unauthorized
|
||||
return $this->unauthorized('Bitte melden Sie sich an');
|
||||
|
||||
// 400 Bad Request
|
||||
return $this->badRequest('Ungültige Anfrage');
|
||||
|
||||
// 500 Internal Server Error
|
||||
return $this->error('Ein Fehler ist aufgetreten');
|
||||
```
|
||||
|
||||
### Datei-Downloads
|
||||
|
||||
Um eine Datei zum Download anzubieten, verwenden Sie die `download`-Methode:
|
||||
|
||||
```php
|
||||
public function download(int $id): Response
|
||||
{
|
||||
$file = File::find($id);
|
||||
|
||||
return $this->download($file->path, $file->name);
|
||||
}
|
||||
```
|
||||
|
||||
### Datei-Streams
|
||||
|
||||
Um eine Datei zu streamen, verwenden Sie die `stream`-Methode:
|
||||
|
||||
```php
|
||||
public function stream(int $id): Response
|
||||
{
|
||||
$video = Video::find($id);
|
||||
|
||||
return $this->stream($video->path, $video->mime_type);
|
||||
}
|
||||
```
|
||||
|
||||
## Dependency Injection
|
||||
|
||||
Das Framework unterstützt Dependency Injection in Controller-Konstruktoren und -Methoden:
|
||||
|
||||
```php
|
||||
class UserController extends Controller
|
||||
{
|
||||
private UserRepository $userRepository;
|
||||
|
||||
public function __construct(UserRepository $userRepository)
|
||||
{
|
||||
$this->userRepository = $userRepository;
|
||||
}
|
||||
|
||||
public function index(Request $request, Logger $logger): Response
|
||||
{
|
||||
$logger->info('Benutzerindex aufgerufen');
|
||||
|
||||
$users = $this->userRepository->all();
|
||||
|
||||
return $this->view('users.index', [
|
||||
'users' => $users
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Middleware
|
||||
|
||||
Sie können Middleware auf Controller-Ebene anwenden, indem Sie die `middleware`-Methode im Konstruktor aufrufen:
|
||||
|
||||
```php
|
||||
class AdminController extends Controller
|
||||
{
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(AuthMiddleware::class);
|
||||
$this->middleware(AdminMiddleware::class);
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
Sie können die Middleware auch auf bestimmte Methoden beschränken:
|
||||
|
||||
```php
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware(AuthMiddleware::class)->only(['index', 'show']);
|
||||
$this->middleware(AdminMiddleware::class)->except(['index', 'show']);
|
||||
}
|
||||
```
|
||||
|
||||
## Ressourcen-Controller
|
||||
|
||||
Ressourcen-Controller bieten eine bequeme Möglichkeit, CRUD-Operationen für eine Ressource zu implementieren. Ein Ressourcen-Controller enthält die folgenden Methoden:
|
||||
|
||||
- `index`: Zeigt eine Liste aller Ressourcen an
|
||||
- `create`: Zeigt ein Formular zum Erstellen einer neuen Ressource an
|
||||
- `store`: Speichert eine neu erstellte Ressource
|
||||
- `show`: Zeigt eine bestimmte Ressource an
|
||||
- `edit`: Zeigt ein Formular zum Bearbeiten einer Ressource an
|
||||
- `update`: Aktualisiert eine bestimmte Ressource
|
||||
- `destroy`: Löscht eine bestimmte Ressource
|
||||
|
||||
Hier ist ein Beispiel für einen Ressourcen-Controller:
|
||||
|
||||
```php
|
||||
class PhotoController extends Controller
|
||||
{
|
||||
public function index(): Response
|
||||
{
|
||||
$photos = Photo::all();
|
||||
|
||||
return $this->view('photos.index', [
|
||||
'photos' => $photos
|
||||
]);
|
||||
}
|
||||
|
||||
public function create(): Response
|
||||
{
|
||||
return $this->view('photos.create');
|
||||
}
|
||||
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$this->validate($request, [
|
||||
'title' => 'required|string|max:255',
|
||||
'image' => 'required|image|max:2048',
|
||||
]);
|
||||
|
||||
$photo = new Photo();
|
||||
$photo->title = $request->input('title');
|
||||
$photo->path = $request->file('image')->store('photos');
|
||||
$photo->save();
|
||||
|
||||
return $this->redirect('/photos')->with('success', 'Foto hochgeladen');
|
||||
}
|
||||
|
||||
public function show(int $id): Response
|
||||
{
|
||||
$photo = Photo::find($id);
|
||||
|
||||
if (!$photo) {
|
||||
return $this->notFound('Foto nicht gefunden');
|
||||
}
|
||||
|
||||
return $this->view('photos.show', [
|
||||
'photo' => $photo
|
||||
]);
|
||||
}
|
||||
|
||||
public function edit(int $id): Response
|
||||
{
|
||||
$photo = Photo::find($id);
|
||||
|
||||
if (!$photo) {
|
||||
return $this->notFound('Foto nicht gefunden');
|
||||
}
|
||||
|
||||
return $this->view('photos.edit', [
|
||||
'photo' => $photo
|
||||
]);
|
||||
}
|
||||
|
||||
public function update(Request $request, int $id): Response
|
||||
{
|
||||
$photo = Photo::find($id);
|
||||
|
||||
if (!$photo) {
|
||||
return $this->notFound('Foto nicht gefunden');
|
||||
}
|
||||
|
||||
$this->validate($request, [
|
||||
'title' => 'required|string|max:255',
|
||||
]);
|
||||
|
||||
$photo->title = $request->input('title');
|
||||
$photo->save();
|
||||
|
||||
return $this->redirect('/photos')->with('success', 'Foto aktualisiert');
|
||||
}
|
||||
|
||||
public function destroy(int $id): Response
|
||||
{
|
||||
$photo = Photo::find($id);
|
||||
|
||||
if (!$photo) {
|
||||
return $this->notFound('Foto nicht gefunden');
|
||||
}
|
||||
|
||||
$photo->delete();
|
||||
|
||||
return $this->redirect('/photos')->with('success', 'Foto gelöscht');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Um einen Ressourcen-Controller zu registrieren, verwenden Sie die `resource`-Methode des Routers:
|
||||
|
||||
```php
|
||||
$router->resource('photos', PhotoController::class);
|
||||
```
|
||||
|
||||
## API-Controller
|
||||
|
||||
API-Controller sind ähnlich wie reguläre Controller, geben jedoch in der Regel JSON-Antworten zurück:
|
||||
|
||||
```php
|
||||
class ApiUserController extends Controller
|
||||
{
|
||||
public function index(): Response
|
||||
{
|
||||
$users = User::all();
|
||||
|
||||
return $this->json([
|
||||
'data' => $users
|
||||
]);
|
||||
}
|
||||
|
||||
public function show(int $id): Response
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
if (!$user) {
|
||||
return $this->json([
|
||||
'error' => 'Benutzer nicht gefunden'
|
||||
], 404);
|
||||
}
|
||||
|
||||
return $this->json([
|
||||
'data' => $user
|
||||
]);
|
||||
}
|
||||
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'password' => 'required|string|min:8',
|
||||
]);
|
||||
|
||||
$user = User::create($request->only(['name', 'email', 'password']));
|
||||
|
||||
return $this->json([
|
||||
'data' => $user,
|
||||
'message' => 'Benutzer erstellt'
|
||||
], 201);
|
||||
}
|
||||
|
||||
public function update(Request $request, int $id): Response
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
if (!$user) {
|
||||
return $this->json([
|
||||
'error' => 'Benutzer nicht gefunden'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$this->validate($request, [
|
||||
'name' => 'string|max:255',
|
||||
'email' => 'email|unique:users,email,' . $id,
|
||||
]);
|
||||
|
||||
$user->fill($request->only(['name', 'email']));
|
||||
$user->save();
|
||||
|
||||
return $this->json([
|
||||
'data' => $user,
|
||||
'message' => 'Benutzer aktualisiert'
|
||||
]);
|
||||
}
|
||||
|
||||
public function destroy(int $id): Response
|
||||
{
|
||||
$user = User::find($id);
|
||||
|
||||
if (!$user) {
|
||||
return $this->json([
|
||||
'error' => 'Benutzer nicht gefunden'
|
||||
], 404);
|
||||
}
|
||||
|
||||
$user->delete();
|
||||
|
||||
return $this->json([
|
||||
'message' => 'Benutzer gelöscht'
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Single Action Controller
|
||||
|
||||
Wenn ein Controller nur eine einzige Aktion ausführt, können Sie einen Single Action Controller erstellen, der die `__invoke`-Methode implementiert:
|
||||
|
||||
```php
|
||||
class ShowDashboardController extends Controller
|
||||
{
|
||||
public function __invoke(Request $request): Response
|
||||
{
|
||||
$stats = [
|
||||
'users' => User::count(),
|
||||
'posts' => Post::count(),
|
||||
'comments' => Comment::count(),
|
||||
];
|
||||
|
||||
return $this->view('dashboard', [
|
||||
'stats' => $stats
|
||||
]);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Um einen Single Action Controller zu registrieren, geben Sie einfach die Controller-Klasse an:
|
||||
|
||||
```php
|
||||
$router->get('/dashboard', ShowDashboardController::class);
|
||||
```
|
||||
|
||||
## Controller-Organisation
|
||||
|
||||
### Namensräume
|
||||
|
||||
Sie können Controller in Namensräumen organisieren, um sie besser zu strukturieren:
|
||||
|
||||
```php
|
||||
namespace App\Application\Controllers\Admin;
|
||||
|
||||
class UserController extends Controller
|
||||
{
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Controller-Gruppen
|
||||
|
||||
Sie können Controller in Gruppen organisieren, indem Sie Routengruppen mit einem Namensraum verwenden:
|
||||
|
||||
```php
|
||||
$router->group('/admin', function (Router $router) {
|
||||
$router->get('/users', [UserController::class, 'index']);
|
||||
$router->get('/posts', [PostController::class, 'index']);
|
||||
})->namespace('App\\Application\\Controllers\\Admin');
|
||||
```
|
||||
|
||||
## Beste Praktiken
|
||||
|
||||
### Schlanke Controller
|
||||
|
||||
Controller sollten schlank sein und sich auf die Verarbeitung von HTTP-Anfragen konzentrieren. Komplexe Geschäftslogik sollte in Service-Klassen oder Modelle ausgelagert werden:
|
||||
|
||||
```php
|
||||
class UserController extends Controller
|
||||
{
|
||||
private UserService $userService;
|
||||
|
||||
public function __construct(UserService $userService)
|
||||
{
|
||||
$this->userService = $userService;
|
||||
}
|
||||
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$this->validate($request, [
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'password' => 'required|string|min:8',
|
||||
]);
|
||||
|
||||
$user = $this->userService->createUser(
|
||||
$request->input('name'),
|
||||
$request->input('email'),
|
||||
$request->input('password')
|
||||
);
|
||||
|
||||
return $this->redirect('/users')->with('success', 'Benutzer erstellt');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Wiederverwendung von Validierungsregeln
|
||||
|
||||
Wenn Sie dieselben Validierungsregeln in mehreren Controllern verwenden, sollten Sie sie in eine separate Klasse auslagern:
|
||||
|
||||
```php
|
||||
class UserValidationRules
|
||||
{
|
||||
public static function forCreation(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'password' => 'required|string|min:8',
|
||||
];
|
||||
}
|
||||
|
||||
public static function forUpdate(int $userId): array
|
||||
{
|
||||
return [
|
||||
'name' => 'string|max:255',
|
||||
'email' => 'email|unique:users,email,' . $userId,
|
||||
];
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Dann können Sie diese Regeln in Ihren Controllern verwenden:
|
||||
|
||||
```php
|
||||
public function store(Request $request): Response
|
||||
{
|
||||
$this->validate($request, UserValidationRules::forCreation());
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
public function update(Request $request, int $id): Response
|
||||
{
|
||||
$this->validate($request, UserValidationRules::forUpdate($id));
|
||||
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Verwendung von Form Requests
|
||||
|
||||
Für komplexe Validierungslogik können Sie Form Request-Klassen erstellen:
|
||||
|
||||
```php
|
||||
class CreateUserRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'name' => 'required|string|max:255',
|
||||
'email' => 'required|email|unique:users,email',
|
||||
'password' => 'required|string|min:8',
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
return [
|
||||
'name.required' => 'Der Name ist erforderlich',
|
||||
'email.unique' => 'Diese E-Mail-Adresse wird bereits verwendet',
|
||||
];
|
||||
}
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return $this->user()->hasPermission('create-users');
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Dann können Sie die Form Request-Klasse in Ihrem Controller verwenden:
|
||||
|
||||
```php
|
||||
public function store(CreateUserRequest $request): Response
|
||||
{
|
||||
// Die Validierung wurde bereits durchgeführt
|
||||
|
||||
$user = User::create($request->validated());
|
||||
|
||||
return $this->redirect('/users')->with('success', 'Benutzer erstellt');
|
||||
}
|
||||
```
|
||||
|
||||
## Weitere Informationen
|
||||
|
||||
- [Routing-Anleitung](routing.md): Erfahren Sie mehr über das Routing-System und wie es mit Controllern interagiert.
|
||||
- [Validierungs-Anleitung](validation.md): Erfahren Sie mehr über die Validierung von Benutzereingaben.
|
||||
- [Middleware-Anleitung](middleware.md): Erfahren Sie mehr über Middleware und wie sie mit Controllern interagiert.
|
||||
- [Architekturübersicht](../architecture/overview.md): Überblick über die Architektur des Frameworks.
|
||||
Reference in New Issue
Block a user