Schnellstart
Vom leeren Ordner zum laufenden Plugin. Der Weg dauert etwa zwanzig Minuten und endet mit einem eigenen API-Endpunkt, den du im Browser siehst.
Voraussetzungen
Ein Entwicklungs-Checkout der Plattform mit laufender Datenbank. Ein Plugin lässt sich zwar eigenständig entwickeln, aber für den ersten Durchlauf ist der Checkout der kürzere Weg.
1. Gerüst erzeugen
bin/console octibiz:plugin:create AcmeShipping
Optionen, wenn die Vorgaben nicht passen:
bin/console octibiz:plugin:create AcmeShipping \
--namespace "Acme\Shipping" \
--label "Acme Versand" \
--dir plugins/ \
--with-entity
Die Namensregeln
Der Name ist der technische Name in PascalCase mit eigenem Prefix. Aus ihm leitet sich alles Weitere ab:
| Eingabe | Namensraum | Plugin-Schlüssel | Modul-Schalter | API-Segment |
|---|---|---|---|---|
AcmeShipping | Acme\Shipping | acme.shipping | module.acme-shipping | /api/v1/acme-shipping |
Der Prefix ist kein Stilmittel. Er verhindert, dass zwei Plugins denselben Schlüssel oder dasselbe Adress-Segment beanspruchen. Beansprucht ein Plugin ein Segment des Kerns, bricht die Installation hart ab, statt die Kern-Route zu überschatten.
Der Name braucht mindestens zwei Wortbestandteile; der erste ist der Prefix des Entwicklers.
2. Was entsteht
plugins/AcmeShipping/
├── composer.json # type: octibiz-plugin + extra.octibiz
├── plugin.json # Paket-Manifest
├── CHANGELOG.md # oberster [x.y.z]-Abschnitt == const VERSION
├── README.md
├── src/
│ ├── AcmeShippingPlugin.php # Bundle
│ ├── AcmeShippingDescriptor.php # Selbstbeschreibung
│ ├── ApiResource/AcmeShippingExampleResource.php
│ ├── State/AcmeShippingExampleProvider.php
│ ├── Security/AcmeShippingPermissionProvider.php
│ ├── Security/AcmeShippingVoter.php
│ ├── Catalog/AcmeShippingStandardDataProvider.php
│ ├── EventListener/AcmeShippingWorkItemCreatedListener.php
│ └── Resources/icon.svg
└── frontend/
├── plugin.manifest.ts
└── locales/de.ts, en.ts
Bei einem Fremd-Plugin kommen tests/, phpunit.xml.dist und ein CI-Arbeitsablauf dazu, dazu die Entwicklungs-Abhängigkeit auf das SDK-Paket.
3. Registrieren
Zwei Einträge, beide im Host. Ohne sie existiert das Plugin für die Anwendung nicht.
Autoload in der composer.json der Instanz:
{
"autoload": {
"psr-4": {
"Acme\\Shipping\\": "plugins/AcmeShipping/src/"
}
}
}
composer dump-autoload
Bundle in config/plugins.php:
return [
Acme\Shipping\AcmeShippingPlugin::class => ['all' => true],
];
4. Installieren und einschalten
bin/console doctrine:migrations:migrate --no-interaction
bin/console octibiz:plugin:install acme.shipping --activate
Die Reihenfolge ist wichtig: Der Installations-Befehl führt keine Migrationen aus. Er erfasst das Katalog-Eigentum und legt den Modul-Schalter an, und zwar deaktiviert. Ohne --activate antworten alle Routen des Plugins weiter mit 404.
Warum deaktiviert: Der Schalter eines Plugins ist fail-closed. Fehlt die Zeile oder steht sie auf aus, ist die Route nicht erreichbar. Das ist die umgekehrte Logik zum Kern, dessen Module ohne Eintrag als eingeschaltet gelten.
5. Prüfen, dass es läuft
bin/console octibiz:plugin:list
Die Zeile zeigt Version, Vertrauensstufe, Aktiv-Zustand und die Zahl der gehaltenen Katalogzeilen. Steht dort aktiv, antwortet auch der Beispiel-Endpunkt:
curl -H "Authorization: Bearer <token>" https://<instanz>/api/v1/acme-shipping/examples
6. Den Generator-Rest entfernen
Das Gerüst legt eine Beispiel-Ressource mit Platzhalter-Zeilen an. Die muss raus, bevor das Plugin ausgeliefert wird. Sie ist nicht nur in der OpenAPI-Beschreibung sichtbar, sondern auch im Werkzeug-Katalog für den KI-Zugang. Eine KI hält die Platzhalter dort für echte Fachdaten.
Ersetze AcmeShippingExampleResource durch deine erste eigene Ressource oder lösche sie samt Provider.
Der häufigste Anfängerfehler
Ein neues API-Präfix wird eingeführt, aber nicht in getRouteSegments() des Descriptors eingetragen. Die Folge ist unauffällig und gefährlich: Für ein undeklariertes Segment greift kein Gate. Die Route bleibt erreichbar, auch wenn das Modul ausgeschaltet ist.
Jedes neue Präfix gehört in denselben Zug in den Descriptor.
Eigenständig entwickeln
Ohne Host-Checkout gibt es die Vertragsfläche als eigene Pakete. Beide folgen der Versionsachse des Plugin-Vertrags, nicht der Systemversion:
{
"require-dev": { "octibiz/plugin-sdk": "~3.15.0" }
}
{
"devDependencies": { "@octibiz/plugin-sdk": "~3.15.0" }
}
Das PHP-Paket bringt AbstractPlugin, die Vertrags-Registry, alle Verträge, die eingefrorenen Ereignisklassen und die Übergabeformen mit. Damit laufen Autovervollständigung, statische Analyse und eigenständige Unit-Tests ohne Zugriff auf die Host-Quellen.
Nur als Entwicklungs-Abhängigkeit. Zur Laufzeit liefert die Instanz die echten Klassen; in einer laufenden Installation darf das SDK nie liegen, sonst gäbe es jede Klasse zweimal.
Nicht enthalten sind Host-Klassen, die in keiner eingefrorenen Signatur vorkommen: Entities, API-Ressourcen, Repositories und die Dienste dahinter. Für Integrationstests gegen die laufende Plattform brauchst du weiterhin einen Checkout.
Weiter
- Anatomie eines Plugins — was jede Datei tut
- Backend — Datenmodell, API, Rechte, Hintergrundverarbeitung
- Oberfläche — Ansichten, Andockstellen, Navigation
- Testen — wo Tests liegen und warum nicht im Plugin
- Lebenszyklus und Befehle — installieren, aktualisieren, entfernen