Migrations 
Database migrations are version control for your database, allowing you to modify your database schema in a structured and organized way. AvelPress migrations are inspired by Laravel's migration system.
Introduction 
Migrations allow you to:
- Create and modify database tables
 - Add and remove columns
 - Create indexes and foreign keys
 - Seed initial data
 - Version control your database schema
 
Creating Migrations 
Migration Files 
Migration files are stored in the database/migrations directory and follow this naming convention:
YYYY_MM_DD_HHMMSS_description_of_migration.phpBasic Migration Structure 
php
<?php
use AvelPress\Database\Migrations\Migration;
use AvelPress\Database\Schema\Schema;
return new class extends Migration
{
    /**
     * Run the migrations.
     */
    public function up()
    {
        Schema::create('users', function ($table) {
            $table->id();
            $table->string('name');
            $table->string('email')->unique();
            $table->timestamps();
        });
    }
    /**
     * Reverse the migrations.
     */
    public function down()
    {
        Schema::dropIfExists('users');
    }
};Table Operations 
Creating Tables 
Schema::create() 
Create a new table.
php
Schema::create('posts', function ($table) {
    $table->id();
    $table->string('title');
    $table->text('content');
    $table->string('status')->default('draft');
    $table->timestamps();
});Table Options 
php
Schema::create('posts', function ($table) {
    $table->id();
    $table->string('title');
    // ... other columns
}, [
    'engine' => 'InnoDB',
    'charset' => 'utf8mb4',
    'collation' => 'utf8mb4_unicode_ci'
]);Modifying Tables 
Schema::table() 
Modify an existing table.
php
Schema::table('users', function ($table) {
    $table->string('phone')->nullable();
    $table->dropColumn('old_column');
    $table->renameColumn('old_name', 'new_name');
});Dropping Tables 
Schema::drop() / Schema::dropIfExists() 
php
// Drop table (will fail if table doesn't exist)
Schema::drop('posts');
// Drop table if it exists
Schema::dropIfExists('posts');Column Types 
String Columns 
php
$table->string('name');                    // VARCHAR(255)
$table->string('name', 100);               // VARCHAR(100)
$table->text('description');               // TEXT
$table->longText('content');               // LONGTEXT
$table->char('code', 10);                  // CHAR(10)Numeric Columns 
php
$table->integer('views');                  // INT
$table->bigInteger('big_number');          // BIGINT
$table->smallInteger('small_number');      // SMALLINT
$table->decimal('price', 8, 2);            // DECIMAL(8,2)
$table->float('rating', 3, 1);             // FLOAT(3,1)
$table->double('coordinates', 15, 8);      // DOUBLE(15,8)Date and Time Columns 
php
$table->date('birth_date');                // DATE
$table->time('start_time');                // TIME
$table->datetime('created_at');            // DATETIME
$table->timestamp('updated_at');           // TIMESTAMP
$table->timestamps();                      // created_at & updated_atBoolean and Binary 
php
$table->boolean('is_active');              // BOOLEAN
$table->binary('data');                    // BLOBSpecial Columns 
php
$table->id();                              // Auto-increment primary key
$table->uuid('uuid');                      // UUID column
$table->json('metadata');                  // JSON column (MySQL 5.7+)
$table->enum('status', ['draft', 'published', 'archived']);Column Modifiers 
Nullable and Default Values 
php
$table->string('name')->nullable();        // Allow NULL
$table->string('status')->default('active'); // Default value
$table->integer('views')->default(0);
$table->timestamp('created_at')->useCurrent(); // Use CURRENT_TIMESTAMPIndexes 
php
$table->string('email')->unique();         // Unique index
$table->string('name')->index();           // Regular index
$table->index(['user_id', 'created_at']);  // Composite index
$table->index('email', 'idx_user_email');  // Named indexAuto Increment 
php
$table->id();                              // Auto-increment primary key
$table->bigInteger('id')->autoIncrement()->primary(); // Custom auto-incrementComments 
php
$table->string('name')->comment('User full name');
$table->integer('views')->comment('Page view count');Foreign Key Constraints 
Basic Foreign Keys 
php
// Add foreign key
$table->foreignId('user_id')->constrained();
// Custom foreign key
$table->foreignId('category_id')->constrained('categories');
// Foreign key with custom column
$table->unsignedBigInteger('author_id');
$table->foreign('author_id')->references('id')->on('users');Foreign Key Actions 
php
$table->foreignId('user_id')
    ->constrained()
    ->onUpdate('cascade')
    ->onDelete('cascade');
$table->foreignId('category_id')
    ->constrained()
    ->onDelete('set null');Dropping Foreign Keys 
php
Schema::table('posts', function ($table) {
    $table->dropForeign(['user_id']);
    $table->dropForeign('posts_user_id_foreign'); // By name
});Indexes 
Creating Indexes 
php
Schema::table('users', function ($table) {
    $table->index('email');                 // Single column
    $table->index(['first_name', 'last_name']); // Composite
    $table->unique('username');             // Unique index
    $table->index('created_at', 'idx_created'); // Named index
});Dropping Indexes 
php
Schema::table('users', function ($table) {
    $table->dropIndex(['email']);          // By column
    $table->dropIndex('users_email_index'); // By name
    $table->dropUnique(['username']);      // Drop unique
});Index Types 
php
$table->index('title');                    // Regular index
$table->unique('email');                   // Unique index
$table->primary(['id', 'type']);           // Composite primary key
$table->fullText('content');               // Full-text index (MySQL)Column Operations 
Adding Columns 
php
Schema::table('users', function ($table) {
    $table->string('phone')->nullable()->after('email');
    $table->text('bio')->after('name');
    $table->timestamp('verified_at')->nullable();
});Modifying Columns 
php
Schema::table('users', function ($table) {
    $table->string('name', 100)->change();  // Change length
    $table->string('email')->nullable()->change(); // Make nullable
    $table->renameColumn('name', 'full_name');
});Dropping Columns 
php
Schema::table('users', function ($table) {
    $table->dropColumn('phone');
    $table->dropColumn(['temp1', 'temp2']); // Multiple columns
});WordPress Integration 
Table Prefixes 
AvelPress automatically handles WordPress table prefixes:
php
// This creates {wp_prefix}my_custom_table
Schema::create('my_custom_table', function ($table) {
    $table->id();
    $table->string('name');
});WordPress-specific Columns 
php
Schema::create('posts', function ($table) {
    $table->id();
    $table->string('post_title');
    $table->longText('post_content');
    $table->string('post_status', 20)->default('publish');
    $table->string('post_type', 20)->default('post');
    $table->unsignedBigInteger('post_author');
    $table->datetime('post_date');
    $table->datetime('post_modified');
    // Foreign key to WordPress users table
    $table->foreign('post_author')->references('ID')->on('users');
});Integration with WordPress Tables 
php
Schema::create('user_profiles', function ($table) {
    $table->id();
    $table->unsignedBigInteger('user_id');
    $table->text('bio')->nullable();
    $table->string('website')->nullable();
    $table->timestamps();
    // Reference WordPress users table
    $table->foreign('user_id')->references('ID')->on('users')->onDelete('cascade');
    $table->unique('user_id');
});Running Migrations 
Automatic Migration 
Migrations can be run automatically when your plugin is activated:
php
// In your main plugin file
register_activation_hook(__FILE__, function() {
    $migrator = AvelPress::app('migrator');
    $migrator->run();
});Manual Migration 
php
// In your service provider or initialization code
$migrator = AvelPress::app('migrator');
$migrator->run();Migration Status 
php
$migrator = AvelPress::app('migrator');
// Check if migrations are pending
if ($migrator->hasPendingMigrations()) {
    // Run pending migrations
    $migrator->run();
}
// Get migration status
$status = $migrator->getStatus();Advanced Features 
Conditional Migrations 
php
public function up()
{
    // Only create if table doesn't exist
    if (!Schema::hasTable('custom_table')) {
        Schema::create('custom_table', function ($table) {
            $table->id();
            $table->string('name');
        });
    }
    // Only add column if it doesn't exist
    if (!Schema::hasColumn('users', 'phone')) {
        Schema::table('users', function ($table) {
            $table->string('phone')->nullable();
        });
    }
}Data Seeding in Migrations 
php
public function up()
{
    Schema::create('categories', function ($table) {
        $table->id();
        $table->string('name');
        $table->string('slug');
        $table->timestamps();
    });
    // Seed initial data
    DB::table('categories')->insert([
        ['name' => 'Technology', 'slug' => 'technology', 'created_at' => now()],
        ['name' => 'Business', 'slug' => 'business', 'created_at' => now()],
        ['name' => 'Design', 'slug' => 'design', 'created_at' => now()],
    ]);
}Raw SQL in Migrations 
php
public function up()
{
    // Create table with raw SQL
    DB::statement('CREATE TABLE custom_table (
        id INT AUTO_INCREMENT PRIMARY KEY,
        data JSON,
        created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
    )');
    // Add custom index
    DB::statement('CREATE INDEX idx_custom ON custom_table (data->"$.type")');
}Best Practices 
1. Always Provide Down Methods 
php
public function up()
{
    Schema::create('posts', function ($table) {
        // Table definition
    });
}
public function down()
{
    Schema::dropIfExists('posts');
}2. Use Descriptive Names 
php
// Good
2024_01_15_143000_create_user_profiles_table.php
2024_01_15_144500_add_phone_to_users_table.php
// Bad
2024_01_15_143000_migration.php
2024_01_15_144500_update_users.php3. Make Migrations Reversible 
php
public function up()
{
    Schema::table('users', function ($table) {
        $table->string('phone')->nullable();
    });
}
public function down()
{
    Schema::table('users', function ($table) {
        $table->dropColumn('phone');
    });
}4. Handle Large Data Sets 
php
public function up()
{
    Schema::table('users', function ($table) {
        $table->string('full_name')->nullable();
    });
    // Update in chunks for large tables
    User::chunk(1000, function ($users) {
        foreach ($users as $user) {
            $user->update([
                'full_name' => $user->first_name . ' ' . $user->last_name
            ]);
        }
    });
}5. Test Migrations 
Always test your migrations in a development environment before deploying:
php
// Test up migration
$migrator->run();
// Test down migration
$migrator->rollback();This migration system provides a robust way to manage your database schema changes while maintaining compatibility with WordPress conventions and best practices.
