Implement Connection Configuration Fields¶
Use this guide when adding user-facing configuration fields to a new plugin. After completing these steps, merchants will see a form rendered by the connection widget when they configure their sync connection.
Prerequisites¶
- You have a plugin class that extends
AbstractPluginand is registered inPluginRegistry. If not, complete Implement a System Plugin first.
1. Create the config class¶
Create a class in the same namespace as your plugin (e.g. app/Integrations/Acme/) that implements ConnectionConfigContract:
<?php
declare(strict_types=1);
namespace App\Integrations\Acme;
use App\ConnectionConfig\ConnectionConfigSchema;
use App\ConnectionConfig\Fields\MultiSelectField;
use App\ConnectionConfig\Fields\RadioField;
use App\ConnectionConfig\Fields\SelectField;
use App\Contracts\ConnectionConfigContract;
use App\Enums\SyncDataType;
use App\Enums\SyncDirection;
use App\Enums\SyncFrequency;
class AcmeConnectionConfig implements ConnectionConfigContract
{
public static function schema(): ConnectionConfigSchema
{
return ConnectionConfigSchema::make([
SelectField::make('direction')
->label('Sync direction')
->options(static::supportedDirections())
->required(),
MultiSelectField::make('data_types')
->label('Data to sync')
->options(static::supportedDataTypes())
->required(),
RadioField::make('frequency')
->label('Sync frequency')
->options(SyncFrequency::class)
->required(),
]);
}
/** @return list<SyncDataType> */
public static function supportedDataTypes(): array
{
return SyncDataType::cases();
}
/** @return list<SyncDirection> */
public static function supportedDirections(): array
{
return SyncDirection::cases();
}
/** @return array<string, mixed> */
public static function defaultConfiguration(): array
{
return [
'direction' => SyncDirection::Inbound->value,
'data_types' => array_map(static fn (SyncDataType $t) => $t->value, static::supportedDataTypes()),
'frequency' => SyncFrequency::Daily->value,
];
}
}
schema() returns a ConnectionConfigSchema containing an ordered list of field objects. Each field serializes to a JSON shape that the widget reads to render the form.
supportedDataTypes() and supportedDirections() return the subset of enum cases this integration actually supports. Passing these to ->options() ensures the widget only presents valid choices for this platform — not all values of the global enum.
defaultConfiguration() returns the values that will be pre-populated when a connection is first created.
2. Choosing and limiting field types¶
Pick the right field type for each setting. The full reference is in Connection Config Fields.
Single-choice settings — use SelectField for a dropdown or RadioField for inline radio buttons:
use App\ConnectionConfig\Fields\SelectField;
use App\ConnectionConfig\Fields\RadioField;
SelectField::make('direction')
->label('Sync direction')
->options(static::supportedDirections()) // list<BackedEnum>
->required(),
RadioField::make('frequency')
->label('Sync frequency')
->options(SyncFrequency::class) // class-string<BackedEnum> — all cases
->required(),
Multi-choice settings — use MultiSelectField when the merchant can pick multiple values:
use App\ConnectionConfig\Fields\MultiSelectField;
MultiSelectField::make('data_types')
->label('Data to sync')
->options(static::supportedDataTypes())
->required(),
Boolean settings — use ToggleField for on/off flags:
use App\ConnectionConfig\Fields\ToggleField;
ToggleField::make('include_tax')
->label('Include tax in order totals')
->required(),
To restrict a SelectField, MultiSelectField, or RadioField to a subset of an enum, return only the relevant cases from supportedDataTypes()/supportedDirections() and pass the result to ->options():
public static function supportedDirections(): array
{
// This platform only supports inbound sync.
return [SyncDirection::Inbound];
}
3. Implement HasConnectionConfiguration on the plugin¶
Open your plugin class and add the HasConnectionConfiguration interface. Delegate both methods to the config class:
<?php
declare(strict_types=1);
namespace App\Integrations\Acme;
use App\ConnectionConfig\ConnectionConfigSchema;
use App\Contracts\HasConnectionConfiguration;
use App\Services\AbstractPlugin;
class AcmePlugin extends AbstractPlugin implements HasConnectionConfiguration
{
// ... existing methods ...
public function connectionConfigurationSchema(): ConnectionConfigSchema
{
return AcmeConnectionConfig::schema();
}
/** @return array<string, mixed> */
public function defaultConnectionConfiguration(): array
{
return AcmeConnectionConfig::defaultConfiguration();
}
}
Once this interface is in place, SystemConnectionObserver::creating() will automatically write the default configuration into any new SystemConnection for this driver — no manual call is needed.
4. Reading configuration values at runtime¶
Saved configuration lives in system_connections.configuration (a JSON column, cast to array). Access it through the SystemConnection passed into your plugin methods:
protected function fetchBulkExportBatches(SystemConnection $connection, ExportRequest $request, Closure $onBatch): void
{
$direction = $connection->configuration['direction'] ?? SyncDirection::Inbound->value;
$dataTypes = $connection->configuration['data_types'] ?? [];
// Use $direction and $dataTypes to parameterise the API call.
}
Validate before use
Configuration is merchant-supplied and may be stale if the schema changes after a connection is saved. Guard against missing or unexpected values with ?? fallbacks or explicit validation before using them to drive API calls.
See also¶
- Connection Config Fields — all field types, serialized shapes, and
options()input formats - Connection Widget — how the schema is served and how the widget renders it
- Embed the Widget — how to place the widget on an external site
- WooCommerce Plugin reference — a complete real implementation of every step above