Developer Portal
Plugin Development

Database Migrations

Plugins that require custom database tables can include a migrations/ directory containing standard Laravel migration files. AIPostify handles executing and tracking plugin database schema updates automatically.

Folder & File Structure

Place your migration files inside {plugin-slug}/migrations/ using standard Laravel timestamped filenames: {timestamp}_{description}.php. Each migration file should return an anonymous class extending Illuminate\Database\Migrations\Migration.

Verbatim Example: postify-announcements Migration

This is the exact migration file from content/plugins/postify-announcements/migrations/2026_07_27_000001_create_announcements_table.php:

<?php

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

return new class extends Migration
{
    /**
     * Run the migrations for Postify Announcements plugin.
     */
    public function up(): void
    {
        Schema::create('announcements', function (Blueprint $table) {
            $table->id();
            $table->text('message');
            $table->string('style', 50)->default('info');
            $table->timestamps();
        });
    }

    /**
     * Reverse the migrations.
     */
    public function down(): void
    {
        Schema::dropIfExists('announcements');
    }
};

When Migrations Run

Plugin migrations run automatically when a site administrator activates the plugin — not on install or ZIP upload.

Rationale: An uploaded plugin sits inactive until an administrator explicitly turns it on. Postponing database modifications until activation ensures that inactive plugins do not modify the site's database schema, adhering to standard CMS design principles.

Idempotency & History Tracking

AIPostify maintains a dedicated plugin_migrations database table (completely separate from Laravel core's internal migrations table) to record every migration file that has been applied per plugin slug.

Because execution history is persisted, deactivating and reactivating a plugin will not re-run or duplicate already-applied migrations.

Deactivate vs. Uninstall

⚠️ CRITICAL: Deactivation Never Touches Your Tables

Deactivating a plugin simply toggles its active state and executes its deactivate() hook. Migrations are NEVER rolled back on deactivation. Your tables and data remain intact.

Deleting / Uninstalling an inactive plugin triggers a full migration rollback. The core calls the down() method of each applied migration in reverse order before removing the plugin directory and database record. This permanently drops tables and columns — plugin authors must write down() methods carefully, and site owners should understand that uninstalling a plugin is destructive.

Failure Handling

If an exception or syntax error occurs while running a migration during activation:

  • The entire activation process is immediately aborted.
  • The plugin remains in an inactive state.
  • No record is inserted into plugin_migrations for the failed migration.
  • An error message with the exception details is presented to the administrator.

Database DDL Limitations

ℹ️ Note on MySQL / MariaDB DDL Statements

In MySQL and MariaDB, DDL statements (such as CREATE TABLE or ALTER TABLE) trigger an implicit commit. If a plugin contains multiple migration files and one fails halfway through activation, previously executed DDL statements cannot be rolled back automatically by database transactions. Always test migration files thoroughly on a development environment before releasing a plugin build.

See It In Action

Download postify-announcements Reference Plugin

The official sample plugin includes a working migrations/ directory creating the announcements table.

Get Reference Plugin

Last verified against AIPostify core. © 2026 AIPostify Marketplace Developer Documentation.