Migrun: A Minimalist, Dependency-Injection First PHP Migration Runner
These articles are AI-generated summaries. Please check the original sources for full details.
Why I Built Migrun
Andrej Rypo developed Migrun to eliminate the technical debt associated with legacy PHP migration tools like Phinx and Phpmig. The system provides an interface-driven approach that allows for autowiring dependencies directly from PSR-11 containers.
Why This Matters
Standalone PHP migration tools often force developers into outdated PHP 5 patterns and rigid inheritance structures that conflict with modern dependency injection practices. In technical reality, database-agnostic builders add unnecessary abstraction layers for features most projects never utilize, while tight coupling to CLI frameworks prevents flexible integration into diverse application architectures.
Key Insights
- Service container integration in tools like Phinx often requires global static access hacks rather than standard dependency injection (Rypo, 2026).
- Migrun eliminates rigid class hierarchies by using interfaces and composition instead of requiring the extension of an AbstractMigration class.
- Query builders introduce unnecessary overhead as most projects never switch databases; Migrun prioritizes raw SQL for simplicity and database-specific features.
- Decoupling the runner from CLI frameworks like Symfony Console allows Migrun to be integrated into any environment, including web-based migration lists.
- Modern PHP features like readonly classes and union types are leveraged to create a minimalist tool with zero external runtime dependencies.
Working Examples
Anonymous class migration with autowiring from a service container.
return new class implements Migration { public function up(?PDO $db = null, ?LoggerInterface $logger = null): void { $db->exec("CREATE TABLE users (id INT AUTO_INCREMENT PRIMARY KEY, email VARCHAR(255) NOT NULL UNIQUE)"); $logger->debug("Users table created."); } };
Initializing the Migrun runner using the builder pattern with a PSR-11 container.
$migrun = new MigrunBuilder()->directory(__DIR__ . "/migrations")->container($container)->pdoStorage($container->get(PDO::class))->build(); $migrun->run();
Practical Applications
- Use Case: PHP projects outside Laravel or Symfony ecosystems use Migrun for lightweight database versioning with native service container support.
- Pitfall: Extending heavy base classes in legacy tools creates rigid architectures that are difficult to integrate with custom application logic.
- Use Case: High-performance microservices implement the Migrun Storage interface to track migration history in Redis or alternative backends.
- Pitfall: Relying on database-agnostic builders often forces developers to write raw SQL anyway for complex schemas, negating the builder primary benefit.
References:
- https://dev.to/dakujem/why-i-built-migrun-2moa
- github.com/dakujem/migrun
Continue reading
Next article
Fixing 6 Common OpenClaw Failures and Reducing Maintenance Overhead
Related Content
PHP 8.4 TypeError and ArgumentCountError Playbook: What Breaks and How to Fix It
PHP 8.4 converts legacy E_WARNING messages into fatal TypeError and ArgumentCountError exceptions, requiring immediate code audits for count() and arithmetic operations.
Podium CLI: A Unified Local Development System
Podium CLI simplifies local development by enabling multiple projects—Laravel, WordPress, and more—to run consistently without Docker configuration.
Azure Fundamentals: Implementing Resource Groups for Cloud Infrastructure Organization
David Cletus implements his first Azure Resource Group in the South Africa North region to unify billing and improve latency for African users.