{"id":18895174,"url":"https://github.com/farisc0de/phpmigration","last_synced_at":"2026-02-10T03:01:55.702Z","repository":{"id":115935637,"uuid":"328331042","full_name":"farisc0de/PhpMigration","owner":"farisc0de","description":"Migration Library for PHP","archived":false,"fork":false,"pushed_at":"2025-01-14T20:25:36.000Z","size":40,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-25T23:23:43.485Z","etag":null,"topics":["database","database-migration","framework","migration","migration-tool","mysql","pdo","php","php-library","php-mysql","php7"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/farisc0de.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-01-10T07:52:05.000Z","updated_at":"2025-01-14T20:25:39.000Z","dependencies_parsed_at":"2024-11-25T11:39:35.593Z","dependency_job_id":"9915fcfc-6adf-4457-abd9-f2235a4eaaf6","html_url":"https://github.com/farisc0de/PhpMigration","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farisc0de%2FPhpMigration","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farisc0de%2FPhpMigration/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farisc0de%2FPhpMigration/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/farisc0de%2FPhpMigration/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/farisc0de","download_url":"https://codeload.github.com/farisc0de/PhpMigration/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248514209,"owners_count":21116899,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["database","database-migration","framework","migration","migration-tool","mysql","pdo","php","php-library","php-mysql","php7"],"created_at":"2024-11-08T08:26:56.237Z","updated_at":"2026-02-10T03:01:55.680Z","avatar_url":"https://github.com/farisc0de.png","language":"PHP","readme":"# PhpMigration\n\nEnterprise-ready database migration library for PHP with fluent schema builder, versioning, CLI tools, and multi-database support.\n\n[![PHP Version](https://img.shields.io/badge/php-%3E%3D8.1-8892BF.svg)](https://php.net/)\n[![License](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n\n## Features\n\n- **Fluent Schema Builder** - Laravel-like Blueprint API for defining tables\n- **Migration Versioning** - Track and manage migration history with batches\n- **CLI Tools** - Full command-line interface for all migration operations\n- **Multi-Database Support** - MySQL, PostgreSQL, and SQLite drivers\n- **Database Seeding** - Populate your database with test or initial data\n- **Schema Introspection** - Inspect existing database structure\n- **Event System** - Hook into migration lifecycle events\n- **PSR-3 Logging** - Compatible logging implementation\n- **Environment Configuration** - Support for `.env` files\n\n## Requirements\n\n- PHP 8.1 or higher\n- PDO extension\n- One of: pdo_mysql, pdo_pgsql, or pdo_sqlite\n\n## Installation\n\n```bash\ncomposer require farisc0de/phpmigration\n```\n\n## Quick Start\n\n### 1. Create Configuration\n\nCreate a `.env` file in your project root:\n\n```env\nDB_DRIVER=mysql\nDB_HOST=localhost\nDB_PORT=3306\nDB_DATABASE=your_database\nDB_USERNAME=your_username\nDB_PASSWORD=your_password\n```\n\nOr create `config/database.php`:\n\n```php\n\u003c?php\nreturn [\n    'default' =\u003e 'mysql',\n    'connections' =\u003e [\n        'mysql' =\u003e [\n            'driver' =\u003e 'mysql',\n            'host' =\u003e 'localhost',\n            'port' =\u003e 3306,\n            'database' =\u003e 'your_database',\n            'username' =\u003e 'your_username',\n            'password' =\u003e 'your_password',\n            'charset' =\u003e 'utf8mb4',\n        ],\n    ],\n];\n```\n\n### 2. Create a Migration\n\n```bash\n./vendor/bin/migrate make:migration create_users_table --create=users\n```\n\nThis creates a file in `database/migrations/`:\n\n```php\n\u003c?php\n\nuse Farisc0de\\PhpMigration\\Contracts\\MigrationInterface;\nuse Farisc0de\\PhpMigration\\Schema\\SchemaBuilder;\nuse Farisc0de\\PhpMigration\\Schema\\Blueprint;\n\nreturn new class implements MigrationInterface\n{\n    public function up(SchemaBuilder $schema): void\n    {\n        $schema-\u003ecreate('users', function (Blueprint $table) {\n            $table-\u003eid();\n            $table-\u003estring('name');\n            $table-\u003estring('email')-\u003eunique();\n            $table-\u003estring('password');\n            $table-\u003eboolean('is_active')-\u003edefault(true);\n            $table-\u003etimestamps();\n        });\n    }\n\n    public function down(SchemaBuilder $schema): void\n    {\n        $schema-\u003edropIfExists('users');\n    }\n};\n```\n\n### 3. Run Migrations\n\n```bash\n./vendor/bin/migrate migrate\n```\n\n## CLI Commands\n\n| Command | Description |\n|---------|-------------|\n| `migrate` | Run all pending migrations |\n| `migrate:rollback` | Rollback the last batch of migrations |\n| `migrate:reset` | Rollback all migrations |\n| `migrate:refresh` | Reset and re-run all migrations |\n| `migrate:status` | Show the status of each migration |\n| `migrate:install` | Create the migration repository table |\n| `make:migration` | Create a new migration file |\n| `make:seeder` | Create a new seeder class |\n| `db:seed` | Run database seeders |\n\n### Command Options\n\n```bash\n# Run migrations with step mode (each migration in its own batch)\n./vendor/bin/migrate migrate --step\n\n# Rollback last 3 batches\n./vendor/bin/migrate migrate:rollback --step=3\n\n# Create migration for existing table\n./vendor/bin/migrate make:migration add_phone_to_users --table=users\n\n# Specify custom path\n./vendor/bin/migrate migrate --path=/custom/migrations/path\n```\n\n## Schema Builder API\n\n### Column Types\n\n```php\n$table-\u003eid();                          // Auto-incrementing BIGINT primary key\n$table-\u003ebigIncrements('id');           // Auto-incrementing BIGINT\n$table-\u003eincrements('id');              // Auto-incrementing INT\n\n$table-\u003estring('name', 100);           // VARCHAR(100)\n$table-\u003echar('code', 4);               // CHAR(4)\n$table-\u003etext('description');           // TEXT\n$table-\u003emediumText('content');         // MEDIUMTEXT\n$table-\u003elongText('body');              // LONGTEXT\n\n$table-\u003einteger('votes');              // INT\n$table-\u003etinyInteger('level');          // TINYINT\n$table-\u003esmallInteger('rank');          // SMALLINT\n$table-\u003emediumInteger('score');        // MEDIUMINT\n$table-\u003ebigInteger('views');           // BIGINT\n$table-\u003eunsignedInteger('count');      // UNSIGNED INT\n\n$table-\u003efloat('amount', 8, 2);         // FLOAT(8,2)\n$table-\u003edouble('price', 15, 8);        // DOUBLE(15,8)\n$table-\u003edecimal('total', 10, 2);       // DECIMAL(10,2)\n\n$table-\u003eboolean('active');             // TINYINT(1)\n\n$table-\u003edate('birth_date');            // DATE\n$table-\u003edateTime('published_at');      // DATETIME\n$table-\u003etime('alarm_time');            // TIME\n$table-\u003etimestamp('added_at');         // TIMESTAMP\n$table-\u003eyear('graduation_year');       // YEAR\n\n$table-\u003ebinary('data');                // BLOB\n$table-\u003ejson('options');               // JSON\n\n$table-\u003eenum('status', ['draft', 'published']);  // ENUM\n$table-\u003euuid('uuid');                  // CHAR(36)\n```\n\n### Column Modifiers\n\n```php\n$table-\u003estring('email')-\u003enullable();           // Allow NULL\n$table-\u003estring('name')-\u003edefault('Guest');      // Default value\n$table-\u003einteger('votes')-\u003eunsigned();          // UNSIGNED\n$table-\u003estring('email')-\u003eunique();             // UNIQUE constraint\n$table-\u003einteger('id')-\u003eprimary();              // PRIMARY KEY\n$table-\u003estring('bio')-\u003ecomment('User bio');    // Column comment\n$table-\u003estring('phone')-\u003eafter('email');       // Position after column (MySQL)\n$table-\u003estring('id')-\u003efirst();                 // Position first (MySQL)\n$table-\u003etimestamp('created_at')-\u003euseCurrent(); // DEFAULT CURRENT_TIMESTAMP\n$table-\u003etimestamp('updated_at')-\u003euseCurrentOnUpdate(); // ON UPDATE CURRENT_TIMESTAMP\n```\n\n### Indexes\n\n```php\n$table-\u003eprimary('id');                         // Primary key\n$table-\u003eprimary(['first', 'last']);            // Composite primary key\n$table-\u003eunique('email');                       // Unique index\n$table-\u003eindex('state');                        // Basic index\n$table-\u003eindex(['account_id', 'created_at']);   // Composite index\n$table-\u003efullText('body');                      // Full-text index (MySQL)\n$table-\u003espatialIndex('location');              // Spatial index (MySQL)\n```\n\n### Foreign Keys\n\n```php\n// Simple foreign key\n$table-\u003eforeignId('user_id')-\u003econstrained();\n\n// With options\n$table-\u003eforeignId('user_id')\n    -\u003econstrained('users', 'id')\n    -\u003eonDelete('CASCADE')\n    -\u003eonUpdate('CASCADE');\n\n// Manual foreign key\n$table-\u003eforeign('user_id')\n    -\u003ereferences('id')\n    -\u003eon('users')\n    -\u003eonDelete('CASCADE');\n```\n\n### Timestamps \u0026 Soft Deletes\n\n```php\n$table-\u003etimestamps();              // created_at and updated_at\n$table-\u003esoftDeletes();             // deleted_at for soft deletes\n$table-\u003erememberToken();           // remember_token for auth\n```\n\n### Polymorphic Relationships\n\n```php\n$table-\u003emorphs('taggable');        // taggable_id and taggable_type\n$table-\u003enullableMorphs('taggable'); // Nullable morphs\n$table-\u003euuidMorphs('taggable');    // UUID morphs\n```\n\n## Database Seeding\n\n### Create a Seeder\n\n```bash\n./vendor/bin/migrate make:seeder UsersSeeder\n```\n\n```php\n\u003c?php\n\nnamespace Database\\Seeders;\n\nuse Farisc0de\\PhpMigration\\Seeders\\Seeder;\n\nclass UsersSeeder extends Seeder\n{\n    public function run(): void\n    {\n        $this-\u003einsert('users', [\n            [\n                'name' =\u003e 'Admin',\n                'email' =\u003e 'admin@example.com',\n                'password' =\u003e password_hash('secret', PASSWORD_DEFAULT),\n            ],\n            [\n                'name' =\u003e 'User',\n                'email' =\u003e 'user@example.com',\n                'password' =\u003e password_hash('secret', PASSWORD_DEFAULT),\n            ],\n        ]);\n\n        // Call other seeders\n        $this-\u003ecall(PostsSeeder::class);\n    }\n}\n```\n\n### Run Seeders\n\n```bash\n./vendor/bin/migrate db:seed\n./vendor/bin/migrate db:seed UsersSeeder\n```\n\n## Programmatic Usage\n\n```php\n\u003c?php\n\nuse Farisc0de\\PhpMigration\\Database\\Connection;\nuse Farisc0de\\PhpMigration\\Schema\\SchemaBuilder;\nuse Farisc0de\\PhpMigration\\Schema\\Grammars\\MySqlGrammar;\nuse Farisc0de\\PhpMigration\\Migrations\\Migrator;\nuse Farisc0de\\PhpMigration\\Migrations\\MigrationRepository;\n\n// Create connection\n$connection = Connection::create([\n    'driver' =\u003e 'mysql',\n    'host' =\u003e 'localhost',\n    'database' =\u003e 'myapp',\n    'username' =\u003e 'root',\n    'password' =\u003e '',\n]);\n\n// Create schema builder\n$grammar = new MySqlGrammar();\n$schema = new SchemaBuilder($connection, $grammar);\n\n// Create table\n$schema-\u003ecreate('posts', function ($table) {\n    $table-\u003eid();\n    $table-\u003estring('title');\n    $table-\u003etext('content');\n    $table-\u003eforeignId('user_id')-\u003econstrained();\n    $table-\u003etimestamps();\n});\n\n// Check if table exists\nif ($schema-\u003ehasTable('posts')) {\n    // Modify table\n    $schema-\u003etable('posts', function ($table) {\n        $table-\u003estring('slug')-\u003eafter('title');\n        $table-\u003eindex('slug');\n    });\n}\n\n// Drop table\n$schema-\u003edropIfExists('posts');\n```\n\n## Schema Introspection\n\n```php\nuse Farisc0de\\PhpMigration\\Schema\\SchemaInspector;\n\n$inspector = new SchemaInspector($connection);\n\n// Get all tables\n$tables = $inspector-\u003egetTables();\n\n// Check table/column existence\n$inspector-\u003ehasTable('users');\n$inspector-\u003ehasColumn('users', 'email');\n\n// Get column information\n$columns = $inspector-\u003egetColumns('users');\n$type = $inspector-\u003egetColumnType('users', 'email');\n\n// Get indexes and foreign keys\n$indexes = $inspector-\u003egetIndexes('users');\n$foreignKeys = $inspector-\u003egetForeignKeys('posts');\n\n// Get primary key\n$primaryKey = $inspector-\u003egetPrimaryKey('users');\n\n// Get table details\n$details = $inspector-\u003egetTableDetails('users');\n```\n\n## Events\n\n```php\nuse Farisc0de\\PhpMigration\\Support\\EventDispatcher;\n\n$events = new EventDispatcher();\n\n$events-\u003elisten('migration.migrating', function ($payload) {\n    echo \"Running: {$payload['migration']}\\n\";\n});\n\n$events-\u003elisten('migration.migrated', function ($payload) {\n    echo \"Completed: {$payload['migration']}\\n\";\n});\n\n// Pass to migrator\n$migrator = new Migrator($repository, $connection, $grammar, $events);\n```\n\n## Logging\n\n```php\nuse Farisc0de\\PhpMigration\\Support\\Logger;\n\n$logger = new Logger(\n    logFile: 'logs/migrations.log',\n    minLevel: 'info',\n    console: true\n);\n\n$logger-\u003einfo('Migration started');\n$logger-\u003eerror('Migration failed', ['exception' =\u003e $e]);\n```\n\n## Legacy API (v1.x Compatibility)\n\nThe original API is still available for backward compatibility:\n\n```php\nuse Farisc0de\\PhpMigration\\Database;\nuse Farisc0de\\PhpMigration\\Migration;\nuse Farisc0de\\PhpMigration\\Utils;\nuse Farisc0de\\PhpMigration\\Options\\Options;\nuse Farisc0de\\PhpMigration\\Options\\Types;\n\n$db = new Database([\n    'DB_HOST' =\u003e 'localhost',\n    'DB_USER' =\u003e 'root',\n    'DB_PASS' =\u003e '',\n    'DB_NAME' =\u003e 'myapp',\n]);\n\n$migration = new Migration($db, new Utils());\n\n$migration-\u003ecreateTable('users', [\n    ['id', Types::integer(), Options::autoIncrement(), Options::notNull()],\n    ['email', Types::string(255), Options::notNull()],\n    ['created_at', Types::timestamp(), Options::currentTimeStamp()],\n]);\n\n$migration-\u003esetPrimary('users', 'id');\n$migration-\u003esetUnique('users', 'email');\n```\n\n## Testing\n\n```bash\ncomposer test\ncomposer test-coverage\n```\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n\n## Author\n\n**Faris AL-Otaibi** - [FarisCode](https://github.com/farisc0de)\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarisc0de%2Fphpmigration","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffarisc0de%2Fphpmigration","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffarisc0de%2Fphpmigration/lists"}