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

# Paket-Caches in optimize integrieren

> Mit optimizes() aus Laravel 13 binden Sie das Erzeugen und Löschen paketeigener Caches in Ihr Deployment ein. Anhand der Implementierung erläutert: Registrierungsschlüssel, Ausschlüsse, Ausführungsreihenfolge und Exit-Codes bei Fehlern.

Wenn Ihr Paket eigene Metadaten vorab erzeugt, reicht es nicht, Nutzer zu bitten, einen eigenen Befehl in ihre Deployment-Schritte aufzunehmen. Bei Updates wird dieser Schritt leicht vergessen. Mit `ServiceProvider::optimizes()` binden Sie die Befehle zum Erzeugen und Löschen in Laravels `optimize` und `optimize:clear` ein.

Diese Seite setzt die [Grundlagen der Paketentwicklung](/de/advanced/package-development) voraus und betrachtet die Implementierung in Laravel Framework `v13.35.0`. Es geht nicht um das Format der Cache-Dateien, sondern um die Vereinbarungen bei Registrierung und Betrieb.

## Befehle und Tasks getrennt registrieren

`commands()` registriert Befehlsklassen, die Sie über Artisan aufrufen können. `optimizes()` ist ein separater Vorgang, der bereits ausführbare Befehlsnamen als Optimierungs-Tasks registriert. Rufen Sie nur Letzteres auf, werden die Befehlsklassen nicht registriert.

Das folgende Beispiel setzt voraus, dass das Paket bereits `CacheMetadataCommand` und `ClearMetadataCommand` implementiert und deren `$signature` jeweils `courier:cache` und `courier:clear-cache` lautet.

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

namespace Acme\Courier;

use Acme\Courier\Console\Commands\CacheMetadataCommand;
use Acme\Courier\Console\Commands\ClearMetadataCommand;
use Illuminate\Support\ServiceProvider;

class CourierServiceProvider extends ServiceProvider
{
    public function boot(): void
    {
        if ($this->app->runningInConsole()) {
            $this->commands([
                CacheMetadataCommand::class,
                ClearMetadataCommand::class,
            ]);

            $this->optimizes(
                optimize: 'courier:cache',
                clear: 'courier:clear-cache',
                key: 'acme-courier',
            );
        }
    }
}
```

Alle Argumente von `optimizes()` sind nullable. Sie können also auch nur das Erzeugen oder nur das Löschen registrieren. Erklären Sie Ihren Nutzern in jedem Fall, mit welchem Schritt der erzeugte Cache invalidiert wird.

## Auch der Registrierungsschlüssel ist eine Vereinbarung mit den Nutzern

`ServiceProvider` speichert Befehle zum Erzeugen im statischen Array `$optimizeCommands` und Befehle zum Löschen in `$optimizeClearCommands`. In beiden Fällen dient `key` als Array-Schlüssel.

Lassen Sie `key` weg, wird der Name aus dem Klassennamen des Providers abgeleitet. Aus `CourierServiceProvider` wird zum Beispiel `courier`. Da nur der Klassenname verwendet wird, können auch gleichnamige Provider aus unterschiedlichen Namespaces kollidieren.

Registrieren Sie denselben Schlüssel erneut, überschreibt der spätere Wert den Befehl auf der jeweiligen Seite. Wenn Sie mehrere Tasks registrieren möchten, verwenden Sie unterschiedliche Schlüssel. Vermeiden Sie außerdem die Schlüssel der Laravel-Standard-Tasks wie `config` oder `routes`. Auch beim Zusammenführen von Standard- und Paket-Tasks werden gleiche String-Schlüssel überschrieben.

<Tip>
  Geben Sie explizit einen Schlüssel an, der Ihr Paket eindeutig identifiziert, etwa `acme-courier`, und behalten Sie ihn über Releases hinweg bei. Der Schlüssel wird als Anzeigename des Tasks verwendet und ist zugleich der Wert, den Nutzer bei `--except` angeben.
</Tip>

## Ausführung nach den Standard-Tasks

In der betrachteten Implementierung fügen beide Befehle das Registrierungs-Array der Pakete in das Array der Standard-Tasks ein und rufen die Einträge dann der Reihe nach auf. Bei kollisionsfreien Schlüsseln werden Paket-Tasks nach den Standard-Tasks angehängt.

| Befehl | Reihenfolge der Standard-Tasks | Danach |
| - | - | - |
| `optimize` | `config:cache` → `event:cache` → `route:cache` → `view:cache` | Registrierte Befehle zum Erzeugen |
| `optimize:clear` | `config:clear` → `cache:clear` → `clear-compiled` → `event:clear` → `route:clear` → `view:clear` | Registrierte Befehle zum Löschen |

```mermaid theme={null}
flowchart TD
    A["boot() des Providers"] --> B["Artisan-Befehle mit commands() registrieren"]
    A --> C["Schlüssel und Befehlsnamen mit optimizes() registrieren"]
    B --> D["php artisan optimize"]
    C --> D
    D --> E["Standard-Caches für Konfiguration, Events, Routen und Views erzeugen"]
    E --> F["courier:cache ausführen"]
    C --> G["php artisan optimize:clear"]
    G --> H["Standard-Caches löschen"]
    H --> I["courier:clear-cache ausführen"]
```

Gehen Sie von dieser Reihenfolge aus: Ihr Befehl zum Erzeugen baut keine anderen Standard-Caches neu auf, sondern erzeugt nur die Daten, die Ihrem Paket gehören. Verwenden Sie `optimizes()` nicht als API, um Abhängigkeiten zwischen mehreren Paketen zu steuern. Brauchen Sie eine strikte Reihenfolge, führen Sie die jeweiligen Befehle explizit nacheinander aus.

<Warning>
  `optimize:clear` enthält auch `cache:clear` und löscht damit ebenfalls die Daten im Standard-Cache-Store. Wenn Sie nur den paketeigenen Cache löschen möchten, führen Sie `courier:clear-cache` direkt aus. Gestalten Sie auch den Löschbefehl Ihres Pakets so, dass er nicht den gesamten gemeinsam genutzten Store leert, sondern nur die Schlüssel oder Dateien löscht, die dem Paket gehören.
</Warning>

## Nach Schlüssel oder Befehlsname ausschließen

Die Option `--except` beider Befehle nimmt kommagetrennte Werte entgegen. Leerzeichen vor und nach jedem Wert werden entfernt, und alle Tasks, deren Schlüssel oder Befehlsname übereinstimmt, werden ausgeschlossen.

```bash theme={null}
php artisan optimize --except=acme-courier
php artisan optimize --except=courier:cache
php artisan optimize:clear --except=acme-courier,cache
```

Die ersten beiden Zeilen schließen denselben Task zum Erzeugen aus. Die dritte schließt den Lösch-Task des Pakets und das Standard-`cache:clear` aus. `cache` ist dabei ein Task-Schlüssel und kein paketeigener Name.

Ein Ausschluss gilt nur für den jeweiligen Aufruf. Er deaktiviert weder die Registrierung im Provider, noch löscht er automatisch früher erzeugte Paket-Caches.

## FAIL eines Tasks und Exit-Code des übergeordneten Befehls unterscheiden

`OptimizeCommand` und `OptimizeClearCommand` rufen jeden Task mit `callSilently()` auf und geben an die Task-Anzeige weiter, ob der Exit-Code `0` ist. Die normale Ausgabe der Unterbefehle wird nicht angezeigt. Um die Ursache eines Fehlers zu untersuchen, führen Sie den jeweiligen Befehl daher direkt aus.

In Laravel `v13.35.0` geben beide `handle()`-Methoden einen von null verschiedenen Rückgabewert eines Unterbefehls nicht als eigenen Rückgabewert weiter. Auch wenn auf dem Bildschirm `FAIL` erscheint, läuft die Schleife weiter, und ohne Exception ist der Exit-Code des übergeordneten Befehls `0`. Geworfene Exceptions werden dagegen von der Task-Anzeigekomponente erneut geworfen, sodass sich hier nicht dasselbe Fortsetzungsverhalten ergibt.

<Warning>
  Schließen Sie nicht allein aus dem Exit-Code `0` von `php artisan optimize` darauf, dass der Paket-Cache erfolgreich erzeugt wurde. Dieses Verhalten beruht auf der Implementierung der geprüften Version. Prüfen Sie es erneut, wenn Sie die unterstützten Laravel-Versionen aktualisieren.
</Warning>

Ist das Erzeugen des Paket-Caches eine Voraussetzung für das Deployment, wählen Sie einen Ablauf, bei dem Sie den Exit-Code des Unterbefehls direkt prüfen können. Im folgenden Beispiel wird der Paket-Task aus dem Gesamtlauf ausgeschlossen und nach den Standard-Tasks genau einmal direkt ausgeführt.

```bash theme={null}
php artisan optimize --except=acme-courier && php artisan courier:cache
```

Dieses Beispiel spiegelt einen Fehler von `courier:cache` im Exit-Code wider, fasst aber keine von null verschiedenen Exit-Codes der Standard-Tasks zusammen. Müssen Sie in Ihrem Deployment auch Fehler der Standard-Tasks zuverlässig erkennen, führen Sie die benötigten Befehle einzeln aus und prüfen Sie jeweils den Exit-Code.

## Update-sichere Caches entwerfen und prüfen

Legen Sie neben der Registrierung auch die Verantwortlichkeiten der Befehle und der lesenden Seite fest.

* Das Erzeugen führt bei wiederholter Ausführung mit derselben Eingabe zum selben Zustand und aktiviert bei einem Abbruch keine unvollständigen Daten.
* Das Löschen schließt auch dann erfolgreich ab, wenn kein Cache existiert, und löscht weder veröffentlichte Konfigurationen der Nutzer noch persistente Daten.
* Ein Befehl, bei dem das Erzeugen fehlschlägt, meldet einen Fehler und gibt einen von null verschiedenen Wert zurück. Auch die lesende Seite behandelt einen beschädigten Cache nicht bedingungslos als gültig.
* Ändern Sie das Cache-Format, weisen Sie Nutzer darauf hin, dass der Cache neu erzeugt werden muss, und ziehen Sie auch einen Neustart lang laufender Prozesse in Betracht.

Prüfen Sie zusätzlich zu den Tests des Pakets in der nutzenden Anwendung die folgenden Punkte. Da die Registrierungs-Arrays statisch sind, achten Sie auch darauf, dass Registrierungen zwischen Tests im selben Prozess erhalten bleiben können.

| Zu prüfender Vorgang | Erfolgskriterium |
| - | - |
| Eigene Befehle zum Erzeugen und Löschen direkt ausführen | Im Normalfall `0`, bei fehlgeschlagenem Erzeugen ein von null verschiedener Wert. Auch zweimaliges Löschen ist erfolgreich |
| `optimize` / `optimize:clear` ausführen | Die Paket-Tasks werden je einmal aufgerufen, und der Zustand nach dem Erzeugen bzw. Löschen ist korrekt |
| `--except` mit Schlüssel und Befehlsname angeben | Nur der betroffene Task wird nicht ausgeführt |
| Befehl zum Erzeugen mit einem von null verschiedenen Exit-Code beenden | Die Anzeige `FAIL` und der Exit-Code des übergeordneten Befehls in der geprüften Version lassen sich unterscheiden |
| Nach einem Paket-Update neu erzeugen | Der Cache wird mit neuem Code und neuer Konfiguration erzeugt, und das alte Format wird nicht weiter gelesen |

## Verwandte Seiten

<Columns cols={2}>
  <Card title="Paketkonfiguration zusammenführen und cachen" icon="sliders" href="/de/advanced/package-config-merging">
    Wie das Ergänzen veröffentlichter Konfigurationen mit dem Neuaufbau des Konfigurations-Caches zusammenhängt.
  </Card>

  <Card title="Laravel-Pakete mit Orchestra Testbench testen" icon="flask" href="/de/advanced/package-testing">
    Provider und Artisan-Befehle in der Testumgebung registrieren.
  </Card>
</Columns>

## Herangezogene Primärquellen

* [Offizielle Laravel-Dokumentation: Optimize commands](https://github.com/laravel/docs/blob/13.x/packages.md#optimize-commands)
* [ServiceProvider: optimizes() und Registrierungsschlüssel](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Support/ServiceProvider.php)
* [OptimizeCommand: Tasks und Ausschlüsse](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Foundation/Console/OptimizeCommand.php)
* [OptimizeClearCommand: Lösch-Tasks und Ausführungsreihenfolge](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Foundation/Console/OptimizeClearCommand.php)
* [Command: Rückgabewert von handle() und Exit-Code](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Console/Command.php)
* [Task: Ergebnisanzeige und erneutes Werfen von Exceptions](https://github.com/laravel/framework/blob/v13.35.0/src/Illuminate/Console/View/Components/Task.php)


## Related topics

- [Laravel-Paketentwicklung](/de/advanced/package-development.md)
- [Weiterführende Themen](/de/advanced/index.md)
- [Vorstellung des Blaze-Pakets](/de/blog/blaze-introduction.md)
- [Notification-Kanal - Laravel Bluesky](/de/packages/laravel-bluesky/notification.md)
- [Laravel Notification für Discord (Webhook)](/de/packages/laravel-notification-discord-webhook.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.