Skip to main content
Geneva, Switzerland Call our support
English

Plugin migrations and background jobs

SQL on activate, async work, and uninstall.

Migrations

Place .sql files in migrations/; they run once per site on activation, recorded in cms_plugin_migrations. Document tables in plugin.jsondatabase.tables.

Example migration

CREATE TABLE IF NOT EXISTS cms_my_plugin_items (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  title VARCHAR(255) NOT NULL,
  created_at DATETIME NOT NULL
);

Background jobs

Register handlers in boot():

$context->registerJobHandler('my-plugin.rebuild', function (Job $job, JobHandlerContext $ctx): array {
    // $job->payload, $ctx->pdo, $ctx->projectRoot
    return ['ok' => true, 'message' => 'Done'];
});

$context->enqueueJob('my-plugin.rebuild', ['full' => true]);

Handler return shape: ['ok' => bool, 'message' => '…', 'retry' => bool?, 'chain' => list?].

Cron

*/15 * * * * php bin/cms.php jobs:dispatch && php bin/cms.php jobs:work --limit=20

Built-in job types include schedule.publish_due, media.compress_batch, sitemap.warm, maintenance.purge_scheduled.

Composer dependencies

  • Root metapackage — Add shared libs to repo root composer.json
  • Per-plugin vendorcomposer plugin-deps:prod in each plugin dir

See docs/plugins-dependencies.md for CI and strict checks.

Uninstall

If the plugin root contains uninstall.sql, it runs on delete-from-disk, then cms_plugin_migrations rows for that slug are removed so reinstall can replay migrations.

Circuit breaker

Set PLUGIN_BOOT_CIRCUIT_BREAKER=1 in .env to auto-deactivate plugins that throw during boot.