Octibiz
Demo

Durchsucht Website und Dokumentation gemeinsam. Enter zeigt alle Treffer, Esc schließt.

Quick start

From an empty folder to a running plugin. The path takes about twenty minutes and ends with an API endpoint of your own that you can see in the browser.

Prerequisites

A development checkout of the platform with a running database. A plugin can be developed standalone, but for the first run the checkout is the shorter route.

1. Generate the skeleton

bin/console octibiz:plugin:create AcmeShipping

Options, when the defaults do not fit:

bin/console octibiz:plugin:create AcmeShipping \
  --namespace "Acme\Shipping" \
  --label "Acme Shipping" \
  --dir plugins/ \
  --with-entity

The naming rules

The name is the technical name in PascalCase with your own prefix. Everything else derives from it:

InputNamespacePlugin keyModule switchAPI segment
AcmeShippingAcme\Shippingacme.shippingmodule.acme-shipping/api/v1/acme-shipping

The prefix is not a matter of style. It prevents two plugins from claiming the same key or the same address segment. If a plugin claims a segment belonging to the core, the installation aborts hard rather than shadowing the core route.

The name needs at least two word parts; the first is the developer prefix.

2. What you get

plugins/AcmeShipping/
├── composer.json                       # type: octibiz-plugin + extra.octibiz
├── plugin.json                         # package manifest
├── CHANGELOG.md                        # topmost [x.y.z] section == const VERSION
├── README.md
├── src/
│   ├── AcmeShippingPlugin.php          # bundle
│   ├── AcmeShippingDescriptor.php      # self-description
│   ├── 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

For a third-party plugin you additionally get tests/, phpunit.xml.dist and a CI workflow, plus the development dependency on the SDK package.

3. Register

Two entries, both in the host. Without them the plugin does not exist for the application.

Autoload in the instance composer.json:

{
  "autoload": {
    "psr-4": {
      "Acme\\Shipping\\": "plugins/AcmeShipping/src/"
    }
  }
}
composer dump-autoload

Bundle in config/plugins.php:

return [
    Acme\Shipping\AcmeShippingPlugin::class => ['all' => true],
];

4. Install and enable

bin/console doctrine:migrations:migrate --no-interaction
bin/console octibiz:plugin:install acme.shipping --activate

The order matters: the install command runs no migrations. It records catalogue ownership and creates the module switch, and it creates it disabled. Without --activate every route of the plugin keeps answering with 404.

Why disabled: a plugin switch is fail-closed. If the row is missing or off, the route is not reachable. That is the inverse of the core, whose modules count as enabled without a row.

5. Check that it runs

bin/console octibiz:plugin:list

The row shows version, trust tier, enabled state and the number of catalogue rows held. If it says enabled, the example endpoint answers too:

curl -H "Authorization: Bearer <token>" https://<instance>/api/v1/acme-shipping/examples

6. Remove the generator leftovers

The skeleton ships an example resource with placeholder rows. They must go before the plugin ships. They are visible not only in the OpenAPI description but also in the tool catalogue for AI access, where a model takes the placeholders for real business data.

Replace AcmeShippingExampleResource with your first real resource, or delete it along with its provider.

The most common beginner mistake

A new API prefix is introduced but not added to getRouteSegments() in the descriptor. The consequence is inconspicuous and dangerous: for an undeclared segment no gate applies. The route stays reachable even when the module is switched off.

Every new prefix belongs in the descriptor in the same commit.

Developing standalone

Without a host checkout, the contract surface is available as packages of its own. Both follow the version axis of the plugin contract, not the system version:

{
  "require-dev": { "octibiz/plugin-sdk": "~3.15.0" }
}
{
  "devDependencies": { "@octibiz/plugin-sdk": "~3.15.0" }
}

The PHP package ships AbstractPlugin, the contract registry, every contract, the frozen event classes and the payload types. That gives you autocompletion, static analysis and standalone unit tests without access to the host sources.

Development dependency only. At runtime the instance provides the real classes; the SDK must never sit in a running installation, or every class would exist twice.

Not included are host classes that appear in no frozen signature: entities, API resources, repositories and the services behind them. For integration tests against the running platform you still need a checkout.

Next

plugin.quickstart · Available from version 0.5.0