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

# PHP-Attribute

> Wie Sie die in Laravel 13 eingeführten bzw. erweiterten PHP-Attribute nutzen, um Konfigurationen von Jobs und Modellen deklarativer zu beschreiben.

## Was sind PHP-Attribute?

PHP-Attribute (PHP Attributes) sind eine native, in PHP 8.0 eingeführte Syntax für Metadaten. Sie können Klassen, Methoden, Eigenschaften oder Funktionen mit Metainformationen in der Form `#[AttributeName]` versehen.

Laravel setzt PHP-Attribute im Framework selbst intensiv ein und ermöglicht damit die deklarative Konfiguration von Jobs und Eloquent-Modellen. In Laravel 13 (v13.2.0) akzeptieren die Queue-Attribute nun auch Enums. Anstelle klassischer Klasseneigenschaften oder Methodenüberschreibungen können Sie mit Attributen lesbaren, kompakten Code schreiben.

```php theme={null}
// Klassische Schreibweise
class ProcessOrder implements ShouldQueue
{
    public string $queue = 'orders';
    public string $connection = 'redis';
    public int $tries = 3;
    public array $backoff = [30, 60, 120];
}

// Schreibweise mit Attributen
#[Queue('orders')]
#[Connection('redis')]
#[Tries(3)]
#[Backoff(30, 60, 120)]
class ProcessOrder implements ShouldQueue
{
}
```

<Tip>
  Attribute stehen ab PHP 8.0 zur Verfügung. Da Laravel 13 PHP 8.3 oder höher voraussetzt, können Sie Attribute in allen Umgebungen verwenden.
</Tip>

## Queue-bezogene Attribute

Alle Attribute für Queue-Jobs liegen im Namensraum `Illuminate\Queue\Attributes`.

### `#[Queue]` — Queue-Namen angeben

Gibt die Standard-Queue an, an die der Job gesendet wird.

```php theme={null}
use Illuminate\Queue\Attributes\Queue;

#[Queue('emails')]
class SendWelcomeEmail implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle(): void
    {
        // ...
    }
}
```

Ab v13.2.0 kann statt einer Zeichenkette auch ein Enum übergeben werden.

```php theme={null}
enum QueueName: string
{
    case Emails = 'emails';
    case Orders = 'orders';
    case Notifications = 'notifications';
}

#[Queue(QueueName::Emails)]
class SendWelcomeEmail implements ShouldQueue
{
    // ...
}
```

<Info>
  Das Attribut `#[Queue]` ist auf `Attribute::TARGET_CLASS` gesetzt und kann daher nur auf Klassen angewendet werden.
</Info>

### `#[Connection]` — Verbindung angeben

Gibt die Standard-Queue-Verbindung an, die der Job nutzt.

```php theme={null}
use Illuminate\Queue\Attributes\Connection;

#[Connection('sqs')]
class ProcessPayment implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function handle(): void
    {
        // ...
    }
}
```

Auch hier funktionieren Enums.

```php theme={null}
enum QueueConnection: string
{
    case Redis = 'redis';
    case Sqs = 'sqs';
    case Database = 'database';
}

#[Connection(QueueConnection::Sqs)]
class ProcessPayment implements ShouldQueue
{
    // ...
}
```

### `#[Backoff]` — Backoff-Zeit für Retries angeben

Gibt die Wartezeit (in Sekunden) bis zum erneuten Versuch nach einem fehlgeschlagenen Job an. Mit mehreren Werten können Sie unterschiedliche Wartezeiten pro Retry setzen (variadic).

```php theme={null}
use Illuminate\Queue\Attributes\Backoff;

// Feste Wartezeit (bei allen Retries 60 Sekunden)
#[Backoff(60)]
class SendEmail implements ShouldQueue
{
    // ...
}

// Unterschiedliche Wartezeiten pro Retry (exponentielles Backoff)
#[Backoff(30, 60, 120)]
class ProcessOrder implements ShouldQueue
{
    // ...
}
```

Ein Blick in die Implementierung von `Backoff` zeigt, dass die Klasse für variadic Argumente ausgelegt ist.

```php theme={null}
// Implementierung von Illuminate\Queue\Attributes\Backoff
#[Attribute(Attribute::TARGET_CLASS)]
class Backoff
{
    public array|int $backoff;

    public function __construct(array|int ...$backoff)
    {
        $this->backoff = count($backoff) === 1 ? $backoff[0] : $backoff;
    }
}
```

Ein einzelner Wert wird als `int`, mehrere Werte als `array` gespeichert.

### `#[Tries]` — Anzahl der Retries angeben

Gibt die maximale Anzahl an Wiederholungsversuchen bei Fehlschlag an.

```php theme={null}
use Illuminate\Queue\Attributes\Tries;

#[Tries(5)]
class ProcessPayment implements ShouldQueue
{
    // ...
}
```

### `#[Timeout]` — Timeout angeben

Gibt die maximale Laufzeit des Jobs (in Sekunden) an. Nach dieser Zeit wird der Job zwangsweise beendet.

```php theme={null}
use Illuminate\Queue\Attributes\Timeout;

#[Timeout(120)]
class GenerateReport implements ShouldQueue
{
    // ...
}
```

### `#[MaxExceptions]` — Anzahl erlaubter Exceptions angeben

Wird die angegebene Anzahl an Exceptions überschritten, gilt der Job als fehlgeschlagen. Wird in Kombination mit `#[Tries]` genutzt.

```php theme={null}
use Illuminate\Queue\Attributes\MaxExceptions;
use Illuminate\Queue\Attributes\Tries;

#[Tries(10)]
#[MaxExceptions(3)]
class ProcessWebhook implements ShouldQueue
{
    // ...
}
```

### `#[UniqueFor]` — Eindeutigkeitsdauer angeben

Gibt die Sperrdauer (in Sekunden) an, während der ein Job nicht mehrfach ausgeführt wird. Nutzung in Kombination mit `ShouldBeUnique`.

```php theme={null}
use Illuminate\Contracts\Queue\ShouldBeUnique;
use Illuminate\Queue\Attributes\UniqueFor;

#[UniqueFor(3600)]
class SyncUserData implements ShouldQueue, ShouldBeUnique
{
    // ...
}
```

### `#[DeleteWhenMissingModels]` — bei fehlendem Modell löschen

Wenn das vom Job abhängige Eloquent-Modell nicht gefunden wird, wird der Job nicht als Fehler markiert, sondern gelöscht (übersprungen).

```php theme={null}
use Illuminate\Queue\Attributes\DeleteWhenMissingModels;

#[DeleteWhenMissingModels]
class SendOrderConfirmation implements ShouldQueue
{
    public function __construct(
        protected Order $order,
    ) {}

    public function handle(): void
    {
        // Existiert $order nicht, wird dieser Job gelöscht
    }
}
```

### `#[WithoutRelations]` — Beziehungen ausschließen

Sorgt dafür, dass beim Serialisieren des Jobs die Model-Relationen nicht mitgeführt werden. So werden die an die Queue übertragenen Daten schlanker.

```php theme={null}
use Illuminate\Queue\Attributes\WithoutRelations;

#[WithoutRelations]
class ExportUser implements ShouldQueue
{
    public function __construct(
        protected User $user,
    ) {}
}
```

### `#[FailOnTimeout]` — Timeout als Fehler werten

Registriert einen Timeout als Job-Fehlschlag (standardmäßig gilt ein Timeout nicht als Fehler).

```php theme={null}
use Illuminate\Queue\Attributes\FailOnTimeout;
use Illuminate\Queue\Attributes\Timeout;

#[Timeout(30)]
#[FailOnTimeout]
class ProcessLongTask implements ShouldQueue
{
    // ...
}
```

## Mehrere Queue-Attribute kombinieren

Sie können diese Attribute kombinieren, um das Verhalten eines Jobs deklarativ zu konfigurieren.

```php theme={null}
use Illuminate\Queue\Attributes\Backoff;
use Illuminate\Queue\Attributes\Connection;
use Illuminate\Queue\Attributes\DeleteWhenMissingModels;
use Illuminate\Queue\Attributes\FailOnTimeout;
use Illuminate\Queue\Attributes\MaxExceptions;
use Illuminate\Queue\Attributes\Queue;
use Illuminate\Queue\Attributes\Timeout;
use Illuminate\Queue\Attributes\Tries;

#[Queue('payments')]
#[Connection('redis')]
#[Tries(3)]
#[Backoff(30, 60, 120)]
#[Timeout(60)]
#[MaxExceptions(2)]
#[DeleteWhenMissingModels]
class ProcessPayment implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public function __construct(
        protected Order $order,
    ) {}

    public function handle(PaymentService $payment): void
    {
        $payment->charge($this->order);
    }
}
```

## Eloquent-bezogene Attribute

Die Eloquent-Modell-Attribute liegen im Namensraum `Illuminate\Database\Eloquent\Attributes`. Laravel 13 fügt zahlreiche Attribute hinzu.

### `#[ScopedBy]` — Global Scope angeben

Über ein Attribut geben Sie die Global-Scope-Klasse an, die automatisch auf das Modell angewendet werden soll. Vererbung wird unterstützt; über das Flag `IS_REPEATABLE` können mehrere Scopes angegeben werden.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\ScopedBy;

#[ScopedBy(ActiveScope::class)]
class User extends Model
{
    // Die Registrierung in booted() entfällt
}
```

Zum Zuweisen mehrerer Scopes wiederholen Sie das Attribut oder übergeben ein Array.

```php theme={null}
// Wiederholte Angabe (IS_REPEATABLE)
#[ScopedBy(ActiveScope::class)]
#[ScopedBy(VerifiedScope::class)]
class User extends Model
{
}

// Sammelangabe als Array
#[ScopedBy([ActiveScope::class, VerifiedScope::class])]
class User extends Model
{
}
```

Zum Vergleich die klassische `booted()`-Methode:

```php theme={null}
// Klassische Schreibweise
class User extends Model
{
    protected static function booted(): void
    {
        static::addGlobalScope(new ActiveScope);
        static::addGlobalScope(new VerifiedScope);
    }
}
```

### `#[ObservedBy]` — Observer angeben

Über ein Attribut geben Sie die Observer-Klasse an, die dem Modell zugeordnet werden soll. Wie `ScopedBy` ist auch dieses Attribut `IS_REPEATABLE`.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\ObservedBy;

#[ObservedBy(UserObserver::class)]
class User extends Model
{
}
```

Auch mehrere Observer können angegeben werden.

```php theme={null}
#[ObservedBy(UserObserver::class)]
#[ObservedBy(AuditObserver::class)]
class User extends Model
{
}
```

Die klassische Registrierung im `AppServiceProvider` entfällt.

```php theme={null}
// Klassische Schreibweise (AppServiceProvider)
public function boot(): void
{
    User::observe(UserObserver::class);
}
```

### `#[UseEloquentBuilder]` — eigenen Query Builder angeben

Über ein Attribut geben Sie den eigenen Eloquent-Builder an, den das Modell verwenden soll.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\UseEloquentBuilder;

#[UseEloquentBuilder(UserQueryBuilder::class)]
class User extends Model
{
}
```

```php theme={null}
namespace App\Builders;

use Illuminate\Database\Eloquent\Builder;

class UserQueryBuilder extends Builder
{
    public function active(): static
    {
        return $this->where('active', true);
    }

    public function verified(): static
    {
        return $this->whereNotNull('email_verified_at');
    }
}
```

```php theme={null}
// Anwendungsbeispiel (typsichere Methodenaufrufe)
$users = User::query()->active()->verified()->get();
```

### `#[CollectedBy]` — eigene Collection angeben

Über ein Attribut geben Sie die eigene Collection-Klasse an, die als Modell-Collection verwendet werden soll.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\CollectedBy;

#[CollectedBy(UserCollection::class)]
class User extends Model
{
}
```

```php theme={null}
namespace App\Collections;

use Illuminate\Database\Eloquent\Collection;

class UserCollection extends Collection
{
    public function admins(): static
    {
        return $this->filter(fn (User $user) => $user->is_admin);
    }

    public function active(): static
    {
        return $this->filter(fn (User $user) => $user->active);
    }
}
```

### `#[Table]` — Tabelleneinstellungen gebündelt angeben

Sie können Tabellenname, Primärschlüssel, Timestamps und weitere tabellenbezogene Einstellungen mit einem einzigen Attribut angeben.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\Table;

#[Table(name: 'system_users', key: 'user_id', timestamps: false)]
class SystemUser extends Model
{
}
```

Die konfigurierbaren Optionen von `Table` sind:

| Parameter      | Entsprechende Eigenschaft | Beschreibung                                        |
| -------------- | ------------------------- | --------------------------------------------------- |
| `name`         | `$table`                  | Tabellenname                                        |
| `key`          | `$primaryKey`             | Spaltenname des Primärschlüssels                    |
| `keyType`      | `$keyType`                | Typ des Primärschlüssels (`'int'`, `'string'` usw.) |
| `incrementing` | `$incrementing`           | Auto-Increment des Primärschlüssels                 |
| `timestamps`   | `$timestamps`             | Timestamps aktiv/inaktiv                            |
| `dateFormat`   | `$dateFormat`             | Datumsformat                                        |

### `#[Scope]` — Methode als lokalen Scope definieren

Sie können eine Methode ohne `scope`-Präfix als lokalen Eloquent-Scope kennzeichnen.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\Scope;

class User extends Model
{
    #[Scope]
    public function active(Builder $query): void
    {
        $query->where('active', true);
    }

    #[Scope]
    public function verified(Builder $query): void
    {
        $query->whereNotNull('email_verified_at');
    }
}
```

```php theme={null}
// Bisher musste der Methodenname den Präfix „scope" tragen
// public function scopeActive(Builder $query): void

// Mit Attribut wird der Methodenname direkt zum Scope-Namen
User::query()->active()->verified()->get();
```

### `#[UseFactory]` — Factory-Klasse angeben

Über ein Attribut geben Sie die eigene Factory-Klasse an, die das Modell verwenden soll.

```php theme={null}
use Illuminate\Database\Eloquent\Attributes\UseFactory;

#[UseFactory(UserFactory::class)]
class User extends Model
{
}
```

### Weitere Eloquent-Attribute

| Attribut                                                   | Beschreibung                                                             |
| ---------------------------------------------------------- | ------------------------------------------------------------------------ |
| `#[Fillable(...$attributes)]`                              | Erlaubte Spalten für Mass Assignment angeben                             |
| `#[Guarded(...$attributes)]`                               | Für Mass Assignment geschützte Spalten angeben                           |
| `#[Unguarded]`                                             | Mass-Assignment-Schutz deaktivieren                                      |
| `#[Hidden(...$attributes)]`                                | Beim Serialisieren auszuschließende Spalten angeben                      |
| `#[Visible(...$attributes)]`                               | Beim Serialisieren einzuschließende Spalten angeben                      |
| `#[Appends(...$attributes)]`                               | Beim Serialisieren zu ergänzende Accessoren angeben                      |
| `#[Touches(...$relations)]`                                | Beziehungen angeben, deren `updated_at` bei Änderungen aktualisiert wird |
| `#[WithoutTimestamps]`                                     | Timestamps deaktivieren                                                  |
| `#[WithoutIncrementing]`                                   | Auto-Increment des Primärschlüssels deaktivieren                         |
| `#[DateFormat(format: '...')]`                             | Datumsformat angeben                                                     |
| `#[UsePolicy(policyClass: '...')]`                         | Zugehörige Policy-Klasse angeben                                         |
| `#[UseResource(resourceClass: '...')]`                     | Zugehörige API-Resource-Klasse angeben                                   |
| `#[UseResourceCollection(resourceCollectionClass: '...')]` | Zugehörige Resource-Collection-Klasse angeben                            |

## Enum-Unterstützung (neu in v13.2.0)

Ab v13.2.0 akzeptieren `#[Queue]` und `#[Connection]` Enums. Damit können Sie statt String-Literalen typsichere PHP-Enums für Queues und Verbindungen verwenden.

```php theme={null}
// Enum-Definition für Queue-Namen
enum Queue: string
{
    case Default = 'default';
    case High = 'high';
    case Low = 'low';
    case Emails = 'emails';
    case Orders = 'orders';
}

// Enum-Definition für Verbindungen
enum Connection: string
{
    case Redis = 'redis';
    case Sqs = 'sqs';
    case Database = 'database';
    case Sync = 'sync';
}
```

```php theme={null}
use Illuminate\Queue\Attributes\Queue;
use Illuminate\Queue\Attributes\Connection;

// Typsichere Angabe mit Enum
#[Queue(Queue::Orders)]
#[Connection(Connection::Redis)]
class ProcessOrder implements ShouldQueue
{
    // ...
}
```

<Tip>
  Mit Enums vermeiden Sie Tippfehler bei Queue- und Connection-Namen und können IDE-Vervollständigung nutzen. Sehr praktisch, um Queue- und Connection-Namen anwendungsweit an einer Stelle zu verwalten.
</Tip>

## Vergleich mit klassischen Klasseneigenschaften

### Vorteile der Attribute

* **Deklarativ** — das Verhalten des Jobs ist sofort am Anfang der Klasse ersichtlich
* **Typsicher** — mit Enums profitieren Sie von IDE-Vervollständigung und Typprüfung
* **Vererbungsfreundlich** — Attribute der Elternklasse lassen sich in Unterklassen überschreiben
* **Weniger Code** — Property-Deklarationen und Method-Overrides entfallen

### Nachteile der Attribute

* **Keine dynamischen Werte** — die Argumente sind Compile-Time-Konstanten; Variablen oder Configwerte sind nicht möglich
* **Einarbeitung nötig** — im Team kann Übung mit der Attribut-Syntax von PHP 8 erforderlich sein

### Wenn dynamische Werte gebraucht werden

Sollen die Werte zur Laufzeit bestimmt werden, verwenden Sie weiterhin Methodenüberschreibungen.

```php theme={null}
class ProcessOrder implements ShouldQueue
{
    // Dynamisches Backoff über eine Methode definieren
    public function backoff(): array
    {
        return [
            config('queue.backoff.first'),
            config('queue.backoff.second'),
        ];
    }
}
```

<Warning>
  Attribute werden zur PHP-Compile-Time ausgewertet. Laufzeitwerte wie `config()` oder `env()` können nicht genutzt werden. Für dynamische Konfigurationen verwenden Sie weiterhin Klasseneigenschaften oder Methoden.
</Warning>

## Interner Aufbau

Laravel liest Attribute intern über die Reflection API aus. Beim Dispatchen eines Jobs erkennt der Trait `ReadsQueueAttributes` (Bestandteil von `InteractsWithQueue`) die Attribute per Reflection und setzt die passenden Eigenschaften.

```php theme={null}
// Vereinfachte interne Vorstellung
$reflection = new ReflectionClass($job);
$attributes = $reflection->getAttributes(Queue::class);

foreach ($attributes as $attribute) {
    $instance = $attribute->newInstance();
    $job->queue = $instance->queue instanceof UnitEnum
        ? $instance->queue->value
        : $instance->queue;
}
```

Eloquent-Modell-Attribute werden analog dazu — etwa im Zeitpunkt von `Model::booted()` — per Reflection ausgelesen.

## Nächste Schritte

<Columns cols={2}>
  <Card title="Mittelstufe: Queues und Jobs" icon="layer-group" href="/de/queues">
    Lernen Sie die grundlegende Nutzung des Laravel-Queue-Systems.
  </Card>

  <Card title="PHP Reflection API" icon="magnifying-glass" href="/de/advanced/php-reflection">
    Detaillierte Erläuterung der Reflection API, mit der Laravel Attribute ausliest.
  </Card>
</Columns>


## Related topics

- [Eloquent Bootable Traits](/de/advanced/eloquent-bootable-traits.md)
- [PHP Reflection API](/de/advanced/php-reflection.md)
- [Laravel-Updates März 2026](/de/blog/changelog/202603.md)
- [Eloquent-Observer und Modell-Events](/de/advanced/eloquent-observers.md)
- [Übersicht der neuen Features in Laravel 13](/de/blog/laravel-13-new-features.md)
