# Routing-Anleitung

Diese Anleitung erklärt, wie das Routing-System des Frameworks funktioniert und wie Sie es effektiv nutzen können.

## Grundlagen des Routings

Das Routing-System ist verantwortlich für das Mapping von HTTP-Anfragen zu Controller-Aktionen. Es ermöglicht Ihnen, URLs zu definieren und festzulegen, welcher Code ausgeführt werden soll, wenn diese URLs aufgerufen werden.

### Routing-Konfiguration

Die Routing-Konfiguration befindet sich in der Datei `config/routes.php`. Diese Datei gibt eine Funktion zurück, die einen Router als Parameter erhält:

```php
<?php

use App\Framework\Routing\Router;
use App\Application\Controllers\HomeController;
use App\Application\Controllers\UserController;

return function (Router $router) {
    // Hier werden Routen definiert
    $router->get('/', [HomeController::class, 'index']);
    $router->get('/users', [UserController::class, 'index']);
    $router->get('/users/{id}', [UserController::class, 'show']);
};
```

## Definieren von Routen

### Grundlegende Routen

Sie können Routen für verschiedene HTTP-Methoden definieren:

```php
// GET-Route
$router->get('/users', [UserController::class, 'index']);

// POST-Route
$router->post('/users', [UserController::class, 'store']);

// PUT-Route
$router->put('/users/{id}', [UserController::class, 'update']);

// PATCH-Route
$router->patch('/users/{id}', [UserController::class, 'update']);

// DELETE-Route
$router->delete('/users/{id}', [UserController::class, 'destroy']);

// Mehrere HTTP-Methoden
$router->match(['GET', 'POST'], '/users/search', [UserController::class, 'search']);

// Alle HTTP-Methoden
$router->any('/users/all', [UserController::class, 'all']);
```

### Routenparameter

Sie können dynamische Segmente in Ihren Routen definieren, indem Sie geschweifte Klammern verwenden:

```php
$router->get('/users/{id}', [UserController::class, 'show']);
$router->get('/posts/{post}/comments/{comment}', [CommentController::class, 'show']);
```

Diese Parameter werden automatisch an die Controller-Methode übergeben:

```php
public function show(Request $request, int $id): Response
{
    $user = User::find($id);
    // ...
}

public function show(Request $request, int $post, int $comment): Response
{
    $post = Post::find($post);
    $comment = Comment::find($comment);
    // ...
}
```

### Optionale Parameter

Sie können optionale Parameter definieren, indem Sie ein Fragezeichen nach dem Parameternamen hinzufügen:

```php
$router->get('/users/{id?}', [UserController::class, 'show']);
```

In diesem Fall müssen Sie in Ihrer Controller-Methode einen Standardwert für den Parameter angeben:

```php
public function show(Request $request, int $id = null): Response
{
    if ($id === null) {
        // Alle Benutzer anzeigen
    } else {
        // Einen bestimmten Benutzer anzeigen
    }
    // ...
}
```

### Parametereinschränkungen

Sie können Einschränkungen für Routenparameter definieren, um sicherzustellen, dass sie einem bestimmten Muster entsprechen:

```php
$router->get('/users/{id}', [UserController::class, 'show'])
    ->where('id', '[0-9]+');

$router->get('/posts/{slug}', [PostController::class, 'show'])
    ->where('slug', '[a-z0-9-]+');

$router->get('/categories/{category}/posts/{post}', [PostController::class, 'showInCategory'])
    ->where(['category' => '[a-z0-9-]+', 'post' => '[0-9]+']);
```

### Benannte Routen

Sie können Routen benennen, um später einfacher auf sie verweisen zu können:

```php
$router->get('/users/{id}', [UserController::class, 'show'])
    ->name('users.show');
```

Sie können dann URLs für benannte Routen generieren:

```php
$url = route('users.show', ['id' => 1]); // /users/1
```

## Routengruppen

Routengruppen ermöglichen es Ihnen, gemeinsame Attribute auf mehrere Routen anzuwenden, ohne sie für jede Route einzeln definieren zu müssen.

### Präfixe

Sie können ein Präfix für eine Gruppe von Routen definieren:

```php
$router->group('/admin', function (Router $router) {
    $router->get('/dashboard', [AdminController::class, 'dashboard']);
    $router->get('/users', [AdminController::class, 'users']);
    $router->get('/settings', [AdminController::class, 'settings']);
});
```

Dies definiert die folgenden Routen:
- `/admin/dashboard`
- `/admin/users`
- `/admin/settings`

### Middleware

Sie können Middleware für eine Gruppe von Routen definieren:

```php
$router->group('', function (Router $router) {
    $router->get('/dashboard', [AdminController::class, 'dashboard']);
    $router->get('/users', [AdminController::class, 'users']);
    $router->get('/settings', [AdminController::class, 'settings']);
})->middleware(AuthMiddleware::class);
```

Sie können auch mehrere Middleware-Klassen angeben:

```php
$router->group('', function (Router $router) {
    // Routen
})->middleware([AuthMiddleware::class, AdminMiddleware::class]);
```

### Namensräume

Sie können einen Namensraum für eine Gruppe von Routen definieren:

```php
$router->group('', function (Router $router) {
    $router->get('/users', ['UserController', 'index']);
    $router->get('/posts', ['PostController', 'index']);
})->namespace('App\\Application\\Controllers\\Admin');
```

In diesem Fall werden die Controller-Klassen im Namensraum `App\Application\Controllers\Admin` gesucht, also `App\Application\Controllers\Admin\UserController` und `App\Application\Controllers\Admin\PostController`.

### Kombinierte Attribute

Sie können mehrere Attribute für eine Gruppe von Routen kombinieren:

```php
$router->group('/admin', function (Router $router) {
    $router->get('/dashboard', ['DashboardController', 'index']);
    $router->get('/users', ['UserController', 'index']);
})
    ->namespace('App\\Application\\Controllers\\Admin')
    ->middleware([AuthMiddleware::class, AdminMiddleware::class])
    ->name('admin.');
```

Dies definiert die folgenden Routen:
- `/admin/dashboard` mit dem Namen `admin.dashboard`
- `/admin/users` mit dem Namen `admin.users`

Beide Routen verwenden die Controller im Namensraum `App\Application\Controllers\Admin` und durchlaufen die `AuthMiddleware` und `AdminMiddleware`.

## Verschachtelte Gruppen

Sie können Routengruppen verschachteln, um komplexere Strukturen zu erstellen:

```php
$router->group('/admin', function (Router $router) {
    $router->get('/dashboard', [AdminController::class, 'dashboard']);
    
    $router->group('/users', function (Router $router) {
        $router->get('/', [AdminUserController::class, 'index']);
        $router->get('/{id}', [AdminUserController::class, 'show']);
        $router->put('/{id}', [AdminUserController::class, 'update']);
        $router->delete('/{id}', [AdminUserController::class, 'destroy']);
    });
    
    $router->group('/settings', function (Router $router) {
        $router->get('/', [AdminSettingsController::class, 'index']);
        $router->put('/general', [AdminSettingsController::class, 'updateGeneral']);
        $router->put('/security', [AdminSettingsController::class, 'updateSecurity']);
    });
});
```

## Fallback-Routen

Sie können eine Fallback-Route definieren, die verwendet wird, wenn keine andere Route übereinstimmt:

```php
$router->fallback([NotFoundController::class, 'index']);
```

## Middleware für einzelne Routen

Sie können Middleware auch für einzelne Routen definieren:

```php
$router->get('/profile', [ProfileController::class, 'index'])
    ->middleware(AuthMiddleware::class);

$router->get('/admin/dashboard', [AdminController::class, 'dashboard'])
    ->middleware([AuthMiddleware::class, AdminMiddleware::class]);
```

## Routen-Caching

Um die Leistung zu verbessern, können Sie die Routing-Konfiguration cachen:

```bash
php console.php route:cache
```

Dies erstellt eine Cache-Datei, die vom Framework verwendet wird, anstatt die Routen bei jeder Anfrage neu zu analysieren.

Um den Cache zu löschen:

```bash
php console.php route:clear
```

## Routen auflisten

Sie können alle registrierten Routen auflisten:

```bash
php console.php route:list
```

Dies zeigt eine Tabelle mit allen Routen, ihren HTTP-Methoden, URLs, Controller-Aktionen und Namen an.

## Routen-Modell-Binding

Das Framework unterstützt Routen-Modell-Binding, das automatisch Modellinstanzen aus Routenparametern auflöst:

```php
$router->get('/users/{user}', [UserController::class, 'show']);
```

In Ihrem Controller:

```php
public function show(Request $request, User $user): Response
{
    // $user ist bereits eine Instanz des User-Modells
    return $this->view('users.show', ['user' => $user]);
}
```

Standardmäßig wird der Parameter `{user}` als ID verwendet, um das Modell zu finden. Sie können dieses Verhalten anpassen, indem Sie die Methode `resolveRouteBinding` in Ihrem Modell überschreiben:

```php
public function resolveRouteBinding(string $value): ?static
{
    return static::where('username', $value)->first();
}
```

## Ressourcen-Routen

Das Framework bietet eine Möglichkeit, schnell Ressourcen-Routen für CRUD-Operationen zu definieren:

```php
$router->resource('photos', PhotoController::class);
```

Dies erstellt die folgenden Routen:

| HTTP-Methode | URI                | Aktion   | Routenname     |
|--------------|-------------------|----------|----------------|
| GET          | /photos           | index    | photos.index   |
| GET          | /photos/create    | create   | photos.create  |
| POST         | /photos           | store    | photos.store   |
| GET          | /photos/{photo}   | show     | photos.show    |
| GET          | /photos/{photo}/edit | edit  | photos.edit    |
| PUT/PATCH    | /photos/{photo}   | update   | photos.update  |
| DELETE       | /photos/{photo}   | destroy  | photos.destroy |

Sie können die generierten Routen einschränken:

```php
$router->resource('photos', PhotoController::class)
    ->only(['index', 'show']);

$router->resource('photos', PhotoController::class)
    ->except(['create', 'store', 'update', 'destroy']);
```

## API-Ressourcen-Routen

Für APIs können Sie API-Ressourcen-Routen definieren, die keine `create` und `edit` Routen enthalten:

```php
$router->apiResource('photos', PhotoApiController::class);
```

Dies erstellt die folgenden Routen:

| HTTP-Methode | URI              | Aktion   | Routenname     |
|--------------|------------------|----------|----------------|
| GET          | /photos          | index    | photos.index   |
| POST         | /photos          | store    | photos.store   |
| GET          | /photos/{photo}  | show     | photos.show    |
| PUT/PATCH    | /photos/{photo}  | update   | photos.update  |
| DELETE       | /photos/{photo}  | destroy  | photos.destroy |

## Verschachtelte Ressourcen

Sie können auch verschachtelte Ressourcen definieren:

```php
$router->resource('photos.comments', PhotoCommentController::class);
```

Dies erstellt Routen wie:
- `/photos/{photo}/comments`
- `/photos/{photo}/comments/{comment}`

## Weitere Informationen

- [Controller-Anleitung](controllers.md): Erfahren Sie mehr über Controller und wie sie mit Routen interagieren.
- [Middleware-Anleitung](middleware.md): Erfahren Sie mehr über Middleware und wie sie im Routing-System verwendet werden.
- [Validierungs-Anleitung](validation.md): Erfahren Sie, wie Sie Benutzereingaben validieren können.
- [Architekturübersicht](../architecture/overview.md): Überblick über die Architektur des Frameworks.
