> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# URL-Generierung

> Erläutert den `url()`-Helper von Laravel sowie das Erzeugen von URLs für benannte Routen, signierte URLs und Controller-Actions.

## Einführung

Laravel bietet mehrere Helper zur Erzeugung von URLs für Ihre Anwendung.
Diese sind besonders nützlich beim Aufbau von Links in Templates oder API-Antworten sowie beim Generieren von Redirect-Antworten zu anderen Stellen Ihrer Anwendung.

## Grundlagen

### URL erzeugen

Mit dem Helper `url` erzeugen Sie beliebige URLs.
Die generierten URLs verwenden automatisch das Schema (HTTP oder HTTPS) und den Host der aktuellen Anfrage.

```php theme={null}
$post = App\Models\Post::find(1);

echo url("/posts/{$post->id}");

// http://example.com/posts/1
```

Für URLs mit Query-String-Parametern nutzen Sie die Methode `query`.

```php theme={null}
echo url()->query('/posts', ['search' => 'Laravel']);

// https://example.com/posts?search=Laravel

echo url()->query('/posts?sort=latest', ['search' => 'Laravel']);

// http://example.com/posts?sort=latest&search=Laravel
```

Wenn Sie einen Parameter übergeben, der bereits im Pfad existiert, wird der bestehende Wert überschrieben.

```php theme={null}
echo url()->query('/posts?sort=latest', ['sort' => 'oldest']);

// http://example.com/posts?sort=oldest
```

Auch Array-Werte lassen sich als Query-Parameter übergeben. Sie werden korrekt indiziert und in der URL kodiert.

```php theme={null}
echo $url = url()->query('/posts', ['columns' => ['title', 'body']]);

// http://example.com/posts?columns%5B0%5D=title&columns%5B1%5D=body

echo urldecode($url);

// http://example.com/posts?columns[0]=title&columns[1]=body
```

### Aktuelle URL abrufen

Wenn Sie dem Helper `url` keinen Pfad übergeben, erhalten Sie eine `Illuminate\Routing\UrlGenerator`-Instanz mit Zugriff auf Informationen zur aktuellen URL.

```php theme={null}
// Aktuelle URL ohne Query-String
echo url()->current();

// Aktuelle URL mit Query-String
echo url()->full();
```

Diese Methoden sind auch über die Facade `URL` verfügbar.

```php theme={null}
use Illuminate\Support\Facades\URL;

echo URL::current();
```

### Vorherige URL abrufen

Manchmal möchten Sie die zuvor besuchte URL kennen. Dafür stellt der Helper `url` die Methoden `previous` und `previousPath` bereit.

```php theme={null}
// Vollständige URL des vorherigen Requests
echo url()->previous();

// Pfad des vorherigen Requests
echo url()->previousPath();
```

Sie können die vorherige URL auch über die Session abrufen.

```php theme={null}
use Illuminate\Http\Request;

Route::post('/users', function (Request $request) {
    $previousUri = $request->session()->previousUri();

    // ...
});
```

Ebenso lässt sich der Routenname der zuletzt besuchten URL über die Session ermitteln.

```php theme={null}
$previousRoute = $request->session()->previousRoute();
```

## URLs für benannte Routen

Der Helper `route` erzeugt URLs für [benannte Routen](./routing#named-routes).
Damit generieren Sie URLs unabhängig von der tatsächlichen Route-URL.
Ändert sich die URL der Route, müssen Sie die Aufrufe von `route` nicht anpassen.

```php theme={null}
Route::get('/post/{post}', function (Post $post) {
    // ...
})->name('post.show');
```

Um für diese Route eine URL zu erzeugen:

```php theme={null}
echo route('post.show', ['post' => 1]);

// http://example.com/post/1
```

Auch Routen mit mehreren Parametern werden unterstützt.

```php theme={null}
Route::get('/post/{post}/comment/{comment}', function (Post $post, Comment $comment) {
    // ...
})->name('comment.show');

echo route('comment.show', ['post' => 1, 'comment' => 3]);

// http://example.com/post/1/comment/3
```

Zusätzliche Array-Werte, die keinen Route-Parametern entsprechen, werden an den Query-String angehängt.

```php theme={null}
echo route('post.show', ['post' => 1, 'search' => 'rocket']);

// http://example.com/post/1?search=rocket
```

### Eloquent-Modelle

Häufig verwenden Sie den Route-Key (üblicherweise den Primärschlüssel) eines Eloquent-Modells zur URL-Erzeugung.
Sie können das Modell direkt als Parameterwert übergeben; `route` extrahiert den Route-Key automatisch.

```php theme={null}
echo route('post.show', ['post' => $post]);
```

### Signierte URLs

Laravel erlaubt es, „signierte" URLs für benannte Routen zu erstellen.
An diese URLs wird ein „Signature"-Hash angehängt, sodass Laravel prüfen kann, ob die URL nach der Erzeugung manipuliert wurde.
Signierte URLs sind besonders praktisch für öffentliche, aber vor Manipulation zu schützende Routen.

Ein Beispiel ist ein öffentlicher „Abmelde"-Link, den Sie per E-Mail an Kunden versenden.
Mit der Methode `signedRoute` der Facade `URL` erstellen Sie signierte URLs.

```php theme={null}
use Illuminate\Support\Facades\URL;

return URL::signedRoute('unsubscribe', ['user' => 1]);
```

Mit dem Argument `absolute` können Sie die Domain aus dem Signatur-Hash ausschließen.

```php theme={null}
return URL::signedRoute('unsubscribe', ['user' => 1], absolute: false);
```

Für eine URL, die nach einer bestimmten Zeit abläuft, verwenden Sie `temporarySignedRoute`.
Beim Verifizieren prüft Laravel, dass der eingebettete Ablauf-Zeitstempel nicht überschritten wurde.

```php theme={null}
use Illuminate\Support\Facades\URL;

return URL::temporarySignedRoute(
    'unsubscribe', now()->plus(minutes: 30), ['user' => 1]
);
```

#### Ablauf der Verifizierung signierter URLs

```mermaid theme={null}
sequenceDiagram
    participant App as Laravel-App
    participant User as Benutzer
    participant Mail as E-Mail
    App->>App: URL::signedRoute() / temporarySignedRoute()
    App->>Mail: Signierte URL per E-Mail senden
    Mail->>User: E-Mail empfangen
    User->>App: URL klicken (GET-Request)
    App->>App: Signatur prüfen<br>hasValidSignature()
    alt Signatur gültig
        App->>User: Aktion ausführen (z. B. Abmeldung)
    else Signatur ungültig oder abgelaufen
        App->>User: 403-Fehler
    end
```

#### Signierte Requests validieren

Um zu prüfen, ob eine eingehende Anfrage eine gültige Signatur besitzt, rufen Sie auf der `Illuminate\Http\Request`-Instanz `hasValidSignature` auf.

```php theme={null}
use Illuminate\Http\Request;

Route::get('/unsubscribe/{user}', function (Request $request) {
    if (! $request->hasValidSignature()) {
        abort(401);
    }

    // ...
})->name('unsubscribe');
```

Sollen bestimmte Query-Parameter ignoriert werden, verwenden Sie `hasValidSignatureWhileIgnoring`.

```php theme={null}
if (! $request->hasValidSignatureWhileIgnoring(['page', 'order'])) {
    abort(401);
}
```

Alternativ zur manuellen Prüfung können Sie die Middleware `signed` (`Illuminate\Routing\Middleware\ValidateSignature`) verwenden. Ohne gültige Signatur wird automatisch ein `403` zurückgegeben.

```php theme={null}
Route::post('/unsubscribe/{user}', function (Request $request) {
    // ...
})->name('unsubscribe')->middleware('signed');
```

Enthält die signierte URL keine Domain, übergeben Sie der Middleware das Argument `relative`.

```php theme={null}
Route::post('/unsubscribe/{user}', function (Request $request) {
    // ...
})->name('unsubscribe')->middleware('signed:relative');
```

#### Reaktion auf ungültige signierte Routen

Wird eine abgelaufene signierte URL aufgerufen, erscheint die generische Fehlerseite mit Status `403`.
Passen Sie das Verhalten in `bootstrap/app.php` an, indem Sie eine eigene render-Closure für die Exception `InvalidSignatureException` definieren.

```php theme={null}
use Illuminate\Routing\Exceptions\InvalidSignatureException;

->withExceptions(function (Exceptions $exceptions): void {
    $exceptions->render(function (InvalidSignatureException $e) {
        return response()->view('errors.link-expired', status: 403);
    });
})
```

## URLs zu Controller-Actions

Die Funktion `action` erzeugt die URL zu einer angegebenen Controller-Action.

```php theme={null}
use App\Http\Controllers\HomeController;

$url = action([HomeController::class, 'index']);
```

Nimmt die Methode Route-Parameter entgegen, übergeben Sie diese als zweites Argument als assoziatives Array.

```php theme={null}
$url = action([UserController::class, 'profile'], ['id' => 1]);
```

## Fluent URI-Objekt

Die URI-Klasse von Laravel bietet eine fluent-Schnittstelle zum Erzeugen und Bearbeiten von URIs als Objekt.

```php theme={null}
use App\Http\Controllers\UserController;
use Illuminate\Support\Uri;

// URI-Instanz aus String erzeugen
$uri = Uri::of('https://example.com/path');

// URI zu Pfad, benannter Route oder Controller-Action
$uri = Uri::to('/dashboard');
$uri = Uri::route('users.show', ['user' => 1]);
$uri = Uri::signedRoute('users.show', ['user' => 1]);
$uri = Uri::temporarySignedRoute('user.index', now()->plus(minutes: 5));
$uri = Uri::action([UserController::class, 'index']);

// URI-Instanz aus der aktuellen Request-URL
$uri = $request->uri();
```

Sobald Sie eine URI-Instanz haben, können Sie sie fluent modifizieren.

```php theme={null}
$uri = Uri::of('https://example.com')
    ->withScheme('http')
    ->withHost('test.com')
    ->withPort(8000)
    ->withPath('/users')
    ->withQuery(['page' => 2])
    ->withFragment('section-1');
```

## Default-Werte für URL-Parameter

Für bestimmte URL-Parameter möchten Sie eventuell requestweite Default-Werte setzen.
Beispiel: Viele Routen enthalten einen `{locale}`-Parameter.

```php theme={null}
Route::get('/{locale}/posts', function () {
    // ...
})->name('post.index');
```

Bei jedem Aufruf von `route` explizit `locale` mitzugeben ist umständlich.
Mit `URL::defaults` legen Sie für den aktuellen Request einen Standardwert fest.
Diese Methode wird in der Regel innerhalb einer [Route-Middleware](./middleware#assigning-middleware-to-routes) aufgerufen, damit sie Zugriff auf den aktuellen Request hat.

```php theme={null}
<?php

namespace App\Http\Middleware;

use Closure;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\URL;
use Symfony\Component\HttpFoundation\Response;

class SetDefaultLocaleForUrls
{
    /**
     * Eingehenden Request verarbeiten.
     *
     * @param  \Closure(\Illuminate\Http\Request): (\Symfony\Component\HttpFoundation\Response)  $next
     */
    public function handle(Request $request, Closure $next): Response
    {
        URL::defaults(['locale' => $request->user()->locale]);

        return $next($request);
    }
}
```

Sobald ein Default für `locale` gesetzt ist, müssen Sie ihn bei `route`-Aufrufen nicht mehr übergeben.

<Info>
  Das Setzen von URL-Defaults kann Laravels implizites Model Binding beeinträchtigen.
  Sorgen Sie über die [Middleware-Priorität](./middleware#sorting-middleware) dafür, dass Ihre Default-Middleware **vor** der `SubstituteBindings`-Middleware ausgeführt wird.
  In `bootstrap/app.php` konfigurieren Sie das über die Methode `priority`.

  ```php theme={null}
  ->withMiddleware(function (Middleware $middleware): void {
      $middleware->prependToPriorityList(
          before: \Illuminate\Routing\Middleware\SubstituteBindings::class,
          prepend: \App\Http\Middleware\SetDefaultLocaleForUrls::class,
      );
  })
  ```
</Info>


## Related topics

- [Remote Sessions](/de/packages/laravel-copilot-sdk/remote-sessions.md)
- [Laravels neues Ökosystem zur Code-Analyse – surveyor / ranger / roster](/de/blog/laravel-ecosystem-analysis.md)
- [Amazon-Bedrock-Treiber für das Laravel AI SDK](/de/packages/laravel-amazon-bedrock.md)
- [PHP AST](/de/advanced/php-ast.md)
- [Laravel Nostr](/de/packages/laravel-nostr.md)
